转载:

[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->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到其他的父类的时候,需要做相应的指针的移动。

三 完!

最新文章

  1. outlook——还原“未读邮件”文件夹
  2. GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
  3. PHP ERROR : Call to undefined function curl_init()
  4. 【Mongo】Linux安装MongoDB
  5. 域名的MX设置及校验方法
  6. es6之Generator
  7. Redis的安装以及在项目中使用Redis的一些总结和体会
  8. 简单说下C#变量的作用域
  9. 杨老师课堂之JavaScript定时器_农夫山泉限时秒杀案例
  10. Oracle day05 索引_数据去重
  11. 【转】WEB服务器与应用服务器的区别
  12. AMBA总线协议AHB、APB、AXI对比分析【转】
  13. Java 反射机制(包括组成、结构、示例说明等内容)
  14. iis 7上发布mvc报错:403.14-Forbidden Web 服务器被配置为不列出此目录的内容
  15. dhroid - Dhdb orm简化sqlite数据库操作
  16. POJ3276(遍历+区间修改)
  17. Python基础学习笔记,进阶学习笔记 出处
  18. python3 from Tkinter import * 和import Tkinter as tk两个区别import Tkinter
  19. [BAT]cmd命令之 cd /d %~dp0
  20. Android字体设置

热门文章

  1. C语言函数篇(三)函数参数高级设计
  2. linux socketpair
  3. P1414 又是毕业季II (数学?
  4. MySQL 5.7远程连接
  5. Category的真相
  6. 【Invert Binary Tree】cpp
  7. SDK接入注意点
  8. PCA学习笔记
  9. php 根据文件内容来判断文件类型
  10. macOS Mojave 深色模式