*** C++虚函数表原理相关代码

#include <iostream>

using namespace std;

class Test{
public:
    void t(void){};
};

class Base {
public:
    virtual void f() {cout<<"base::f"<<endl;}
    virtual void g() {cout<<"base::g"<<endl;}
    virtual void h() {cout<<"base::h"<<endl;}

    int n;
};

class Derive : public Base{
public:
    void g() {cout<<"derive::g"<<endl;}
};


int main () {
    cout<<"size of Base: "<<sizeof(Base)<<endl;
    cout << "size of Test: " << sizeof(Test)<<endl;//Test类中没有虚函数,因此没有虚函数表

    typedef void(*Func)(void);
    Base b;
    Base *d = new Derive();

    Func f=NULL, g=NULL, h=NULL; 
    
    if (sizeof(void*) == sizeof(int))
    {
        int* pvptr = reinterpret_cast<int*>(d);
        int* vptr = reinterpret_cast<int*>(*pvptr); 
        f = (Func)vptr[0];
        g = (Func)vptr[1];
        h = (Func)vptr[2];
    }
    else if (sizeof(void*) == sizeof(long))
    {
        long* pvptr = reinterpret_cast<long*>(d);
        long* vptr = reinterpret_cast<long*>(*pvptr);  
        f = (Func)vptr[0];
        g = (Func)vptr[1];
        h = (Func)vptr[2];
    }
    else if (sizeof(void*) == sizeof(long long))
    {
        long long* pvptr = reinterpret_cast<long long*>(d);
        long long* vptr = reinterpret_cast<long long*>(*pvptr);
        f = (Func)vptr[0];
        g = (Func)vptr[1];
        h = (Func)vptr[2];
    }

    f();
    g();
    h();    
    
    return 0;
}

 下面代码侧面说明,编译器在构造函数末尾处初始化vptr。所以如果在构造函数中调用virtual函数,动态绑定不会起作用,只会调用本类中的virtual函数:

#include <iostream>
using namespace std;

class base
{
public:
    base()
    {
        doSth();
    }
    virtual void doSth(void)
    {
        cout << "I am Base" << endl;
    }
};

class derived: public base
{
public:
    virtual void doSth(void)
    {
        cout << "I am Derived" << endl;
    }
};

int main()
{
    derived b;
    return 0;
}

 下面代码是我自己写的读取虚函数表示例:

#include <iostream>

using namespace std;

class Base{
public:
    void func0(void)
    {
        cout << "Base::func0" <<endl;
    }
    virtual void func1(void)
    {
        cout << "Base::func1" << endl;
    }
    virtual void func2(void)
    {
        cout << "Base::func2" << endl;
    }

private:
    int num1;
    int num2;
};

class Derived: public Base
{
public:
    void func0(void) //当Base中该函数声明为virtual,Derived中不写virtual也一样
    {
        cout << "Derived::func0" <<endl;
    }
    virtual void func1(void)
    {
        cout << "Derived::func1" << endl;
    }
    virtual void func3(void)
    {
        cout << "Derived::func3" << endl;
    }
};

typedef void (*Fun)(void);
template <class T>
inline Fun vTblItem(Base & obj, int i, T)
{
    return (Fun)(*((T)(*(T)(&obj))+i));
}
Fun getVTblItem(Base & obj, int i)
{
    void *p = NULL;
    if (sizeof(void*) == sizeof(int))
    {
        return vTblItem(obj, i, (int*)p);
    }
    else if (sizeof(void*) == sizeof(long))
    {
        return vTblItem(obj, i, (long*)p);
    }
    else if (sizeof(void*) == sizeof(long long))
    {
        return vTblItem(obj, i, (long long*)p);
    }
}

int main()
{
    Derived b;

    getVTblItem (b,0)();
    getVTblItem (b,1)();
    getVTblItem (b,2)();
    
    Base & a = b;
    a.func0();

    return 0;
}

屏幕输出:

Derived::func1                                                                                                                                                                     
Base::func2                                                                                                                                                                        
Derived::func3                                                                                                                                                                     
Base::func0  

如果将

class Base{
public:
    void func0(void)
  ... ...
改为
class Base{
public:
    virtual void func0(void)
  ... ...
则func0()也加入到了虚函数表中,并且是表中第1项。屏幕输出为:
Derived::func0                                                                                                                                                                     
Derived::func1                                                                                                                                                                     
Base::func2                                                                                                                                                                        
Derived::func0

 

posted @ 2018-12-13 20:45  super行者  阅读(193)  评论(0编辑  收藏  举报