c++虚拟继承

来源:互联网 发布:立体图纸设计软件 编辑:程序博客网 时间:2024/06/05 19:37

http://blog.csdn.net/bluedog/article/details/4711169

先看下代码:

struct A{    A(int v=100):X(v){};    virtual void foo(void){}    int X;}; struct B :virtual public A{    B(int v=10):Y(v),A(100){};    virtual void fooB(void){}    int Y;}; struct C : virtual public A{    C(int v=20):Z(v),A(100){}    virtual void fooC(void){}    int Z;};  struct D : public B, public C{    D(int v =40):B(10),C(20),A(100),L(v){}    virtual void fooD(void){}    int L;};  int _tmain(int argc, _TCHAR* argv[]){       A a;    int *ptr;    ptr = (int*)&a;    cout << ptr << " sizeof = " << sizeof(a) <<endl;    for(int i=0;i<sizeof(A)/sizeof(int);i++)    {        if(ptr[i] < 10000)        {             cout << dec << ptr[i]<<endl;        }        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;    }     cout << "--------------------------------------" <<endl;     B b;    ptr = (int*)&b;    cout <<"addr:" << ptr << " sizeof = " << sizeof(b) <<endl;    for(int i=0;i<sizeof(B)/sizeof(int);i++)    {        if(ptr[i] < 10000)        {             cout << dec << ptr[i]<<endl;        }        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;    }     cout << "--------------------------------------" <<endl;       D d;    ptr = (int*)&d;    cout <<"addr:" << ptr << " sizeof = " << sizeof(d) <<endl;    for(int i=0;i<sizeof(D)/sizeof(int);i++)    {        if(ptr[i] < 10000)        {             cout << dec << ptr[i]<<endl;        }        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;    }    return 0;}


如果B虚拟继承A,则B的对象中要增加一个虚拟基类指针,其指向的表的第二项,即从本指针到虚拟基类的偏移。

例如,对象b,的虚拟基类的地址是120+8 = 128


虚拟基类在b对象的最后。


多重继承,继承n个类,有n个续表指针;包括n个虚基类,有n个虚基类指针。




举个例子,

B虚继承A,如果A中有虚函数,则B类对象的开始位置是虚表指针,第二个位置是虚基类的指针。

class A{public:    A():a(1){}    int a;};class B: public virtual A{public:    B():b(2){}    int b;};int main() {    B* b = new B;    A* a = dynamic_cast<A*>(b);    if(a == b)//b先默认转为A*,所以相等     {        std::cout << "equal" << std::endl;    }     else     {        std::cout << "not equal" << std::endl;    }//输出equal    if (int(b) == int(a))     {        std::cout << "equal" << std::endl;    }     else     {        std::cout << "not equal" << std::endl;    }//输出not equal    typedef void (*pFun)(void);    int **ptb = (int **)b;    cout<<ptb[0][0]<<" "<<ptb[0][1]<<endl;    cout<<&((int*)ptb)[1]/*<<" "<<ptb[1][1]*/<<endl;    cout<<&((int*)ptb)[2]<<endl;    cout<<"-------"<<endl;    cout<<a<<endl<<b<<endl;}

output:

equal
not equal
0 8
00701E5C
00701E60
-------
00701E60
00701E58


对象b的内存分布是:


虚基类的地址是 58+8 = 60


a为什么不等于b?

a指向了60的地址,而b指向的还是58



如果在虚继承的继承上又有多态重载?

class A{public:    virtual void fun1()    {        cout<<"A"<<endl;    }    A():a(1){}    int a;};class B: virtual public A{public:    B():b(2){}    virtual void fun1()    {        cout<<"B:fun1"<<endl;    }    virtual void fun2()    {        cout<<"B:fun2"<<endl;    }    int b;};int main() {    B* b = new B;    A* a = dynamic_cast<A*>(b);    if(a == b)     {        std::cout << "equal" << std::endl;    }     else     {        std::cout << "not equal" << std::endl;    }//输出equal    if (int(b) == int(a))     {        std::cout << "equal" << std::endl;    }     else     {        std::cout << "not equal" << std::endl;    }//输出not equal    cout<<sizeof(B)<<endl;    typedef void (*pFun)(void);    int **ptb = (int **)b;   /* int *ptmp = (int *)b;    pFun p = (pFun)((int *)ptmp[0])[0];    p();*/    pFun pfun;    pfun =(pFun) ptb[0][0];   // cout<<ptb[0][0]<<" "<<ptb[0][1]<<endl;    cout<<"first vtb"<<endl;    pfun();    cout<<ptb[1][0]<<" "<<ptb[1][1]<<endl;    cout<<((int*)ptb)[2]<<endl;//B:b    cout<<(int)ptb[3]<<endl;    pfun = (pFun)ptb[4][0];    cout<<"second vtb"<<endl;    pfun();      cout<<((int*)ptb)[5]<<endl;//A:a    cout<<"-------"<<endl;    cout<<a<<endl<<b<<endl;   }


output:

equal
not equal
24
first vtb
B:fun2
-4 12
2
0
second vtb
B:fun1
1
-------
00360A18
00360A08


08 vftable ---->B:fun2()

0c   base_psb---->-4,12

10 B:b

14 0//不知道为什么为0?

18 vftable------>B:fun1()

1c A:a


如果B类变为

class B: virtual public A
{
public:
    B():b(2){}
    virtual void fun1()
    {
        cout<<"B:fun1"<<endl;
    }
    void fun2()
    {
        cout<<"B:fun2"<<endl;
    }
    int b;
};


fun2不是虚函数,所以对象b的开始不是虚函数表指针,而是虚基类指针


 pFun pfun;
   
    cout<<ptb[0][0]<<" "<<ptb[0][1]<<endl;
    
  
   
    cout<<((int*)ptb)[1]<<endl;//B:b
    
     pfun =(pFun) ptb[3][0];
     pfun();


    /*cout<<(int)ptb[3]<<endl;


    pfun = (pFun)ptb[4][0];
    cout<<"second vtb"<<endl;
    pfun();*/
  
    cout<<((int*)ptb)[4]<<endl;//A:a
    cout<<"-------"<<endl;
    cout<<a<<endl<<b<<endl;


output:

equal
not equal
20
0 12
2
B:fun1
1
-------
004D3DB4
004D3DA8


同样,为什么第2项为0?










原创粉丝点击