一 虚继承

1) 代码:

Code
#include <iostream>
using namespace std;

class B
{
public:
    int i;
    virtual void vB(){ cout << "B::vB" << endl; }
    void fB(){ cout << "B::fB" << endl;}
};

class D1 : virtual public B
{
public:
    int x;
    virtual void vD1(){ cout << "D1::vD1" << endl; }
    void fD1(){ cout << "D1::fD1" << endl;}
};

class D2 : virtual public B
{
public:
    int y;
    void vB(){ cout << "D2::vB" << endl;}
    virtual void vD2(){ cout << "D2::vD2" << endl;}
    void fD2(){ cout << "D2::fD2" << endl;}
};

class GD :  public D1, public D2
{
public:
    int a;
    void vB(){ cout << "GD::vB" << endl;}
    void vD1(){cout << "GD::vD1" << endl;}
    virtual void vGD(){cout << "GD::vGD" << endl;}
    void fGD(){cout << "GD::fGD" << endl;}
};

2)类图:

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

4)可视化表示:

5)代码验证:(此时的虚函数表不是以NULL结尾,为什么?)

Code
typedef void (*Fun)();

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

void PrintMemberAndVT(GD *pGD)
{
    int *pRoot = (int*)pGD;

int *pD1VT = (int*)*(pRoot + 0); 
    (*(Fun*)(pD1VT))(); (*(Fun*)(pD1VT +1))();
    int *pVB = (int*)*(pRoot +1);  cout << "vbtable's adress:" << *pVB << endl;
    int *pX = (pRoot + 2); PrintMember(pX);

int *pD2VT = (int*)*(pRoot + 3); 
    (*(Fun*)(pD2VT))();
    int *pVB2 = (int*)*(pRoot +4); cout << "vbtable's adress:" << *pVB2 << endl;
    int *pY = (pRoot + 5); PrintMember(pY);

int *pA = (pRoot + 6); PrintMember(pA);

int *pBVT = (int*)*(pRoot + 7); 
    (*(Fun*)(pBVT))();
    int *pI = (pRoot + 8); PrintMember(pI);
}

void TestVT()
{
    B *pB = new GD();
    GD *pGD = dynamic_cast<GD*>(pB);
    pGD->i = 10;
    pGD->x = 20;
    pGD->y = 30;
    pGD->a = 40;
    PrintMemberAndVT(pGD);
    delete pGD;
}

6)验证代码结果:

7)总结:

虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移。

二 虚继承运行时类型转化

1)代码验证:

Code
void TestDynamicCast()
{
    B *pB = new GD();
    GD *pGD = dynamic_cast<GD*>(pB);
    cout << "GD:" << pGD << endl;
    D1 *pD1 = dynamic_cast<D1*>(pB);
    cout << "D1:" << pD1 << endl;
    D2 *pD2 = dynamic_cast<D2*>(pB);
    cout << "D2:" << pD2 << endl;
    cout << "B:" << pB << endl;
}

2)验证代码结果:

3)总结:

还是从内存布局来看dynamic_cast时地址的变化,第一个基类的地址与子类相同,其他的基类和虚基类需要做偏移。

三 完!

转载于:https://www.cnblogs.com/itech/archive/2009/03/01/1399996.html

[C++对象模型][9]虚继承与虚函数表相关推荐

  1. C++虚函数,虚函数表,虚继承,虚继承表

    一.虚函数 类中用virtual关键字修饰的函数. 作用:主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的 ...

  2. c++虚继承和虚函数和抽象类、接口类,聚合类

    虚继承 虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间.存在二义性). 底层实现原理与编译器相关,一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间, ...

  3. C++中的各种“虚“-- 虚函数、纯虚函数、虚继承、虚基类、虚析构、纯虚析构、抽象类讲解

    C++中的各种"虚" 1. 菱形继承 1.1 虚继承 && 虚基类 1.2 虚基类指针(vbptr)&& 虚基类表(vbtable) 2. 多态 2 ...

  4. C++虚继承与虚函数

    虚继承和虚函数是完全无相关的两个概念. 虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝.这将存在两个问题:其一,浪费存储空间:第二,存在二义性问题,通常可 ...

  5. 继承、虚继承、虚函数内存分布(MSVC下)

    前提知识: 对象的内存中只包含成员变量,存储在栈区或堆区(使用 new 创建对象): 成员函数与对象内存分离,存储在代码区. 对象的大小,可以自己分析,int 四个字节,指针也是四个字节.(在x86中 ...

  6. C++中的虚继承与虚基类

    1.Cpp中的虚继承与虚基类 在多继承时,很容易产生命名冲突的问题,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示: 类A派 ...

  7. 多重继承、虚继承与虚基类

    一.多重继承 单重继承--一个派生类最多只能有一个基类 多重继承--一个派生类可以有多个基类 class 类名: 继承方式 基类1,继承方式 基类2,-. {-.}; 派生类同时继承多个基类的成员,更 ...

  8. 【C++】继承和派生、虚继承和虚基类、虚基类表和虚基类指针

    继承和派生.虚继承和虚基类.虚基类表和虚基类指针 继承和派生 继承概述 继承基本概念 派生类中的成员 继承的内容 派生类定义 派生类访问控制 对象构造和析构 对象构造和析构的调用顺序 继承中的构造和析 ...

  9. C++_虚继承_虚函数_纯虚函数(多继承的二义性,多态)

    基本信息 每一个类都有一个虚表,以及虚表指针; 虚表的内容是编译器决定的,虚表中用于存放虚函数的指针, 程序运行时的类型信息等; 每个多态对象都存放着一个指向当前类型的虚表的指针, 该指针在构造函数中 ...

最新文章

  1. 三下乡辅导孩子计算机知识,【青春“三下乡”】普及家庭教育知识,共促孩子健康成长...
  2. Centos7 上安装Docker
  3. linux磁盘管理原理,Linux操作系统中磁盘存储区管理的原理与技巧
  4. python第三方库numpy-Python第三方库之openpyxl(2)
  5. 彻底弄懂C语言数组名
  6. 除了盖泡面,kindle还可以帮你提高科研效率
  7. 在Qt Designer更改部件类名
  8. 【操作系统】输入输出系统(上)-思维导图
  9. HDU2034 人见人爱A-B【水题】
  10. 二十岁出头,你一无所有,但你却拥有一切
  11. 外贸软件如何提升出口流程管理效率
  12. 香港服务器怎么加速?
  13. 程序员鸡汤_程序员之魂鸡汤
  14. 【小程序】小程序多次扫描不同二维码参数不生效问题
  15. 硬盘克隆大师从入门到精通
  16. 被小伙伴要出来的文章[0]:英语学习
  17. International Classification for Standards 国际标准分类号
  18. continue 当条件不问那么执行你所对比的这个参数
  19. 华为手机哪一款手机是鸿蒙系统_华为鸿蒙系统哪一款手机在用
  20. 【R语言】使用nnet过程中报错Error in eval(predvars, data, env) : object ‘naulong‘ not found

热门文章

  1. 两端外伸梁内力计算机程序,理解材料力学核心问题:梁的弯曲 剪力弯矩图快速软件绘法...
  2. mysql历史命令_MySQL交互技巧
  3. 关闭计算机网络端口,怎么关闭135和500端口?
  4. opencv python教程简书_OpenCV-Python教程:27.图像转换
  5. mysql中int(m)_mysql中int(M) tinyint(M)中M的作用
  6. One-Stage Visual Grounding论文汇总
  7. 完全背包:以重量分阶段
  8. BZOJ 4417 Luogu P3990 [SHOI2013]超级跳马 (DP、矩阵乘法)
  9. 【瞎扯】About Me
  10. λ-矩阵(初等因子)