c++虚拟继承

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;
}

c++虚拟继承_第1张图片

如果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的内存分布是:

c++虚拟继承_第2张图片

虚基类的地址是 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?










你可能感兴趣的:(c++虚拟继承)