菱形虚拟继承

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了菱形虚拟继承相关的知识,希望对你有一定的参考价值。

    最近在学习C++的继承,菱形继承是比较难懂的一部分,所以通过查阅资料后整理了一下思路,也和同学分享了关于菱形虚拟继承的一些东西。

    菱形继承在一般情况下使用不到的,但是通过了解菱形继承,我们 可以了解编译器是如何工作的。

    首先,菱形虚拟继承就是两个基类虚拟继承一个共同的超类,然后两个基类由有一个共同的派生类。

    

技术分享

class Base
{
public:
    void func()
    {
        cout << "Base::func"<<endl;
    }
public:
    int a;
};

class Base1:virtual public Base
{
public :
    virtual void func1()
    {
        cout<<"Base1::func1" <<endl;
    }

    virtual void func2()
    {
        cout<<"Base1::func2" <<endl;
    }

public :
    int b1 ;
};

class Base2:virtual public Base
{
public :
    virtual void func1()
    {
        cout<<"Base2::func1" <<endl;
    }

    virtual void func2()
    {
        cout<<"Base2::func2" <<endl;
    }

public :
    int b2 ;
};


class Derive : public Base1, public Base2
{
public :
    virtual void func1()
    {
        cout<<"Derive::func1" <<endl;
    }

    virtual void func3()
    {
        cout<<"Derive::func3" <<endl;
    }

pubilc :
    int d1 ;
};

在这我们构造出一个Derive的对象d,调用监视窗口,看一下编译器是怎么存的。


技术分享

     我们可以看到,Base1和Base2中都有一个虚函数表指针,编译器就是利用虚函数表指针解决了二义性问题,而且Base1和Base2的虚函数表指针地址都不同,所以他们都有自己的虚表。

int main()
{
    //Test1();
    Derive d;
    d.a = 1;
    d.b1 = 2;
    d.b2 = 3;
    d.d1 = 4;

    return 0;
}

之前的类的数据成员我是设为了public的,方便赋值后直接调出内存来看内存里的变化。然后给数据成员a,b1,b2,d依次赋值然后调出内存看:

技术分享

所以虚拟继承的实质就是利用一个虚基类指针和一个虚函数表指针解决数据的二义性

以上是关于菱形虚拟继承的主要内容,如果未能解决你的问题,请参考以下文章

C++:继承(继承的概念和性质,赋值兼容规则,菱形继承和虚拟继承)

C++进阶第十五篇—C++中的继承(继承的概念+菱形继承+虚拟继承+组合)

C++菱形继承问题与虚拟继承原理

C++菱形继承问题与虚拟继承原理

C++之继承总结(继承的定义与格式,赋值转换,默认成员函数,菱形继承及菱形虚拟继承)

菱形虚拟虚拟继承模型探索