C++虚函数表结构

原文 C++ 虚函数表解析

  1. 相同类的不同对象共享同一虚函数表。
  2. 任何函数指针通过 cout 直接输出为 1,与原文描述有出入,也未找到 linux 每个表的结尾统一表示,待研究。
  3. 用long 类型指针,应其长度和所在机器指针长度一致。
$ g++ test.cpp -o test && ./test

==== vitual function table ====
  [0] --> Derive::f --> Base1::g --> Base1::h --> Derive::g1 --> []
  [1] --> Derive::f --> Base2::g --> Base2::h --> []
  [2] --> Derive::f --> Base3::g --> Base3::h --> []

==== virtual function table shared or not ====
 pVtab:0x55c77563fbe8
pVtab2:0x55c77563fbe8
Share virtual function table between different instances of same class!

==== function pointer output with cout ====
(long*)pFun: 0xfffffffffffffff8
pFun: 1
(long*)pFun: 0xfffffffffffffff0
pFun: 1
(long*)pFun: 0x55c77543b2ba
pFun: 1
(long*)pFun: 0x7fb203e414f8
pFun: 1
(long*)pFun: 0x55c77543d518
pFun: 1
(long*)pFun: 0x300000000
pFun: 1
(long*)pFun: 0x55c77543a50a
pFun: 1
Function pointer have same output with cout.

// test.cpp

#include <iostream>
#include <string>
#include <sstream>
#include <map>

using namespace std;

class Base1 {
public:
    virtual string f() { ostringstream oss; oss << "Base1::f"; return oss.str(); }
    virtual string g() { ostringstream oss; oss << "Base1::g"; return oss.str(); }
    virtual string h() { ostringstream oss; oss << "Base1::h"; return oss.str(); }
};

class Base2 {
public:
    virtual string f() { ostringstream oss; oss << "Base2::f"; return oss.str(); }
    virtual string g() { ostringstream oss; oss << "Base2::g"; return oss.str(); }
    virtual string h() { ostringstream oss; oss << "Base2::h"; return oss.str(); }
};

class Base3 {
public:
    virtual string f() { ostringstream oss; oss << "Base3::f"; return oss.str(); }
    virtual string g() { ostringstream oss; oss << "Base3::g"; return oss.str(); }
    virtual string h() { ostringstream oss; oss << "Base3::h"; return oss.str(); }
};

class Derive : public Base1, public Base2, public Base3 {
public:
    virtual string f() { ostringstream oss; oss << "Derive::f"; return oss.str(); }
    virtual string g1() { ostringstream oss; oss << "Derive::g1"; return oss.str(); }
};

string testFun() {
    return "xxxx";
}

//typedef string(*Fun)(void);
using Fun = string(*)(void);

int main() {
    Fun pFun = NULL;

    Derive d;
    long** pVtab = (long**)&d;

    map<int,int> len_map = {{0,4},{1,3},{2,3}};

#if 1
    cout << endl << "==== vitual function table ====" << endl;
    for (int i = 0; i < 3; ++i) {
        cout << "  [" << i << "]";
        for (int j = 0; j < len_map[i]; ++j) {
            pFun = (Fun)*((long*)*((long*)&d+i)+j);
            cout << " --> " << pFun();
        }
        cout << " --> []" << endl;
    }
#endif

#if 1
    cout << endl << "==== virtual function table shared or not ====" << endl;
    Derive d2;
    long** pVtab2 = (long**)&d2;
    cout << " pVtab:" << *pVtab << endl;
    cout << "pVtab2:" << *pVtab2 << endl;
    if (*pVtab == *pVtab2) {
        cout << "Share virtual function table between different instances of same class!" << endl;
    }
#endif


#if 0
    //Base1's vtable

    pFun = (Fun)*((long*)*((long*)&d+0)+0);
    //pFun = (Fun)pVtab[0][0];
    cout << pFun() << endl;

    pFun = (Fun)*((long*)*((long*)&d+0)+1);
    //pFun = (Fun)pVtab[0][1];
    cout << pFun() << endl;

    pFun = (Fun)*((long*)*((long*)&d+0)+2);
    //pFun = (Fun)pVtab[0][2];
    cout << pFun() << endl;

    //Derive's vtable
    pFun = (Fun)*((long*)*((long*)&d+0)+3);
    //pFun = (Fun)pVtab[0][3];
    cout << pFun() << endl;

    //The tail of the vtable
    pFun = (Fun)*((long*)*((long*)&d+0)+4);
    //pFun = (Fun)pVtab[0][4];
    cout<<pFun<<endl;

    //Base2's vtable

    //pFun = (Fun)*((long*)*((long*)&d+1)+0);
    pFun = (Fun)pVtab[1][0];
    cout << pFun() << endl;

    pFun = (Fun)pVtab[1][1];
    cout << pFun() << endl;

    pFun = (Fun)pVtab[1][2];
    cout << pFun() << endl;
    //The tail of the vtable
    pFun = (Fun)pVtab[1][3];
    cout<<pFun<<endl;

    //Base3's vtable

    pFun = (Fun)*((long*)*((long*)&d+2)+0);
    //pFun = (Fun)pVtab[2][0];
    cout << pFun() << endl;

    pFun = (Fun)pVtab[2][1];
    cout << pFun() << endl;

    pFun = (Fun)pVtab[2][2];
    cout << pFun() << endl;

    //The tail of the vtable
    pFun = (Fun)*((long*)*((long*)&d+2)+3);
    //pFun = (Fun)pVtab[2][3];
    cout<<pFun<<endl;
    return 0;

#endif

#if 1
    cout << endl << "==== function pointer output with cout ====" << endl;
    pFun = (Fun)*((long*)*((long*)&d+0)+4);
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    pFun = (Fun)*((long*)*((long*)&d+1)+3);
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    pFun = (Fun)*((long*)*((long*)&d+2)+2);
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    pFun = (Fun)*((long*)*((long*)&d+2)+3);
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    pFun = (Fun)*((long*)*((long*)&d+2)+4);
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    pFun = (Fun)*((long*)*((long*)&d+2)+5);
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    pFun = &testFun;
    cout << "(long*)pFun: " << (long*)pFun << endl;
    cout << "pFun: " << pFun << endl;

    cout << "Function pointer have same output with cout." << endl;
#endif
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值