[C++对象模型][8]多重继承与虚函数表

一 多重继承

1) 代码:

Code
#include <iostream>
using namespace std;

class B1
{
public:
    
int x;
    
virtual void v1(){ cout << "B1::v1" << endl; }
    
void f1(){cout << "B1::f1" << endl; }
};

class B2
{
public:
    
int y;
    
virtual void v2(){ cout << "B2::v2" << endl; }
    
void f2(){ cout << "B2::f2" << endl; }
};

class B3
{
public:
    
int z;
    
virtual void v3(){ cout << "B3::v3" << endl; }
    
void f3(){ cout << "B3::f3" << endl; }
};

class D : public B1, public B2, public B3
{
public:
    
int a;
    
void v3(){ cout << "D::v3" << endl; }
    
virtual void vD(){ cout << "D::vD" << endl; }
};

 

 

2)类图:

 

3)VS2008的编译选项查看布局:

 

4)可视化表示:

 

5)代码验证:

Code
typedef void (*Fun)();

void PrintMember(int *pI)
{
    cout 
<< *pI << endl;
}
void PrintVT(int *pVT)
{
    
while(*pVT != NULL)
    {
        (
*(Fun*)(pVT))();
        pVT
++;
    }
}

void PrintVTAndMember(B1 *pD)
{
    
int *pRoot = (int*)pD;
    
int *pVTB1 = (int*)*(pRoot + 0);PrintVT(pVTB1);
    
int *pMB1 = pRoot +1; PrintMember(pMB1);
    
int *pVTB2 = (int*)*(pRoot + 2);PrintVT(pVTB2);
    
int *pMB2 = pRoot +3; PrintMember(pMB2);
    
int *pVTB3 = (int*)*(pRoot + 4);PrintVT(pVTB3);
    
int *pMB3 = pRoot +5; PrintMember(pMB3);
}

void TestVT()
{
    B1 
*pB1 = new D();
    D 
*pD = dynamic_cast<D*>(pB1);
    pD
->= 10;
    pD
->= 20;
    pD
->= 30;
    pD
->= 40;
    PrintVTAndMember(pD);
    delete pD;
}

 

 

6) 验证代码运行结果:

 

7)总结:

与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面。

二 多重继承运行时类型转化

1)代码验证:

Code
void TestDynamicCast()
{
    B1 
*pB1 = new D();
    cout 
<< "B1:" << pB1 << endl;
    D 
*pD = dynamic_cast<D*>(pB1);
    cout 
<< "D:"<< pD << endl;
    B2 
*pB2 = dynamic_cast<B2*>(pB1);
    cout 
<< "B2:" << pB2 << endl;
    B3 
*pB3 = dynamic_cast<B3*>(pB1);
    cout 
<< "B3:" << pB3 << endl;
    delete pD;
}

 

2)验证代码的运行结果:

 

3)总结:

从多重继承的内存布局,我们可以看到子类新加入的虚函数被加到了第一个基类的虚函数表,所以当dynamic_cast的时候,子类和第一个基类的地址相同,不需要移动指针,但是当dynamic_cast到其他的父类的时候,需要做相应的指针的移动。

三 完!

posted @ 2009-02-28 10:21  iTech  阅读(...)  评论(...编辑  收藏