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

一 多重继承

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->x = 10;
     pD->y = 20;
     pD->z = 30;
     pD->a = 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到其他的父类的时候,需要做相应的指针的移动。

三 完!

感谢,Thanks!

作者:iTech
出处:http://itech.cnblogs.com/
转载:本文版权归作者iTech所有,转载请注明出处,不得用于商业用途!

C++对象模型系列:

本系列是主要是作者经验的总结且同时参考了大量的网络文章,希望能够给C++的学习者有所帮助,但是由于作者水平有限,难免有错,希望大家能够指出,我将虚心地向大家学习,与大家共同进步!本系列的开发环境是Windows 32+VS2008。

文章:

指针和引用
指针与数组
指针与字符串
堆栈与函数调用
sizeof与对象内存布局
单继承与虚函数表
多重继承与虚函数表
虚继承与虚函数表
类型转化

原文地址:https://www.cnblogs.com/sideny/p/3301937.html