菱形继承-1

菱形继承

c++支持多继承,因此可能出现菱形继承。菱形继承是指,派生类B和派生类C同时继承基类A,派生类D又同时继承B和C,代码如下:

#include "iostream"
using namespace std;

class baseClass
{
private:
    int i;
    char c;
public:
    virtual void virt_fun1(){ cout << "baseClass virt_fun1" << endl; }
    virtual void virt_fun2(){ cout << "baseClass virt_fun2" << endl; }
    void comm_fun1(){ cout << "baseClass comm_fun1" << endl; }
    void comm_fun2(){ cout << "baseClass comm_fun2" << endl; }
    baseClass() { cout << "tihs is baseClass" << endl; }
    ~baseClass() { cout << "~~ baseClass" << endl; }
};

class inheritClass_1 : public baseClass
{
private:
    char c;
public:
    virtual void virt_fun1(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_1() { cout << "tihs is inheritClass_1" << endl; }
    ~inheritClass_1() { cout << "~~ inheritClass_1" << endl; }
};

class inheritClass_2 : public baseClass
{
private:
    char c;
public:
    virtual void virt_fun2(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_2() { cout << "tihs is inheritClass_2" << endl; }
    ~inheritClass_2() { cout << "~~ inheritClass_2" << endl; }
};

class inheritClass_3 : public inheritClass_1, public inheritClass_2
{
private:
    char c;
public:
    virtual void virt_fun1(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun2(){ cout << "inheritClass virt_fun2" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_3() { cout << "tihs is inheritClass_3" << endl; }
    ~inheritClass_3() { cout << "~~ inheritClass_3" << endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    inheritClass_3 a;

    return 0;
}

运行程序,输出如下:
这里写图片描述
从运行结果来看,基类被构造和析构两次,这显然是不合理的(如果派生类inheritClass_3 的对象要访问baseClass类的成员,则由于baseClass的成员存在两份,导致二义性,程序出错)。
inheritClass_3共占用36字节(36字节容易理解)内存,内存分布如下:
这里写图片描述
从内存分布中可以看出
1:inheritClass_3继承inheritClass_1和inheritClass_2时,这两个类又继承baseClass,所以才导致inheritClass_3中保存了两份baseClass的成员。
2:inheritClass_1成员在内存中的地址最低,而后是inheritClass_2的成员,最后才是inheritClass_3的成员。

虚继承 -1

如果派生类B和派生类C同时继承基类A,派生类D同时虚继承B和C,能否解决该问题呢?代码如下:

#include "iostream"
using namespace std;

class baseClass
{
private:
    int i;
    char c;
public:
    virtual void virt_fun1(){ cout << "baseClass virt_fun1" << endl; }
    virtual void virt_fun2(){ cout << "baseClass virt_fun2" << endl; }
    void comm_fun1(){ cout << "baseClass comm_fun1" << endl; }
    void comm_fun2(){ cout << "baseClass comm_fun2" << endl; }
    baseClass() { cout << "tihs is baseClass" << endl; }
    ~baseClass() { cout << "~~ baseClass" << endl; }
};

class inheritClass_1 : public baseClass
{
private:
    char c;
public:
    virtual void virt_fun1(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_1() { cout << "tihs is inheritClass_1" << endl; }
    ~inheritClass_1() { cout << "~~ inheritClass_1" << endl; }
};

class inheritClass_2 : public baseClass
{
private:
    char c;
public:
    virtual void virt_fun2(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_2() { cout << "tihs is inheritClass_2" << endl; }
    ~inheritClass_2() { cout << "~~ inheritClass_2" << endl; }
};

class inheritClass_3 : public virtual inheritClass_1, public virtual inheritClass_2
{
private:
    char c;
public:
    virtual void virt_fun1(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun2(){ cout << "inheritClass virt_fun2" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_3() { cout << "tihs is inheritClass_3" << endl; }
    ~inheritClass_3() { cout << "~~ inheritClass_3" << endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    inheritClass_3 a;

    return 0;
}

问题并没有解决,程序执行结果如下:
这里写图片描述
inheritClass_3占用48字节内存,内存分布如下:
这里写图片描述
由于inheritClass_3虚继承inheritClass_1和inheritClass_2,所以inheritClass_3增加了一个vbptr(4字节),同时由于派生类和基类存在同名虚函数,故多出2×4=8字节的(vtordisp)内存。
下面简单介绍一下vtordisp,参看MSDN“虚继承中派生类重写了基类的虚函数,并且在构造函数或者析构函数中使用指向基类的指针调用了该函数,编译器会为虚基类添加vtordisp域”,所以vtordisp产生条件:
1:派生类重写了虚基类的虚函数。
2:派生类定义了构造函数或者析构函数。
从内存分布中可以看出inheritClass_3虽然同时虚继承inheritClass_1和inheritClass_2,但是inheritClass_1和inheritClass_2在继承baseClass时不是虚继承,从而inheritClass_1和inheritClass_2都包含了一份baseClass,导致inheritClass_3中依旧有两份baseClass。

虚继承-2

由于虚继承-1并不能解决菱形继承的问题,并且从内存分布看inheritClass_1和inheritClass_2各自保留了一份baseClass,那如果inheritClass_1和inheritClass_2都是虚继承baseClass,然后被inheritClass_3继承(非虚继承),是不是就能解决问题呢?代码如下:

#include "iostream"
using namespace std;

class baseClass
{
private:
    int i;
    char c;
public:
    virtual void virt_fun1(){ cout << "baseClass virt_fun1" << endl; }
    virtual void virt_fun2(){ cout << "baseClass virt_fun2" << endl; }
    void comm_fun1(){ cout << "baseClass comm_fun1" << endl; }
    void comm_fun2(){ cout << "baseClass comm_fun2" << endl; }
    baseClass() { cout << "tihs is baseClass" << endl; }
    ~baseClass() { cout << "~~ baseClass" << endl; }
};

class inheritClass_1 : public virtual baseClass
{
private:
    char c;
public:
    virtual void virt_fun1(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_1() { cout << "tihs is inheritClass_1" << endl; }
    ~inheritClass_1() { cout << "~~ inheritClass_1" << endl; }
};

class inheritClass_2 : public virtual baseClass
{
private:
    char c;
public:
    virtual void virt_fun2(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_2() { cout << "tihs is inheritClass_2" << endl; }
    ~inheritClass_2() { cout << "~~ inheritClass_2" << endl; }
};

class inheritClass_3 : public inheritClass_1, public inheritClass_2
{
private:
    char c;
public:
    virtual void virt_fun1(){ cout << "inheritClass virt_fun1" << endl; }
    virtual void virt_fun2(){ cout << "inheritClass virt_fun2" << endl; }
    virtual void virt_fun3(){ cout << "inheritClass virt_fun2" << endl; }
    inheritClass_3() { cout << "tihs is inheritClass_3" << endl; }
    ~inheritClass_3() { cout << "~~ inheritClass_3" << endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    inheritClass_3 a;

    return 0;
}

程序运行结果:
这里写图片描述
从运行结果看,生成inheritClass_3时,只有一份baseClass,问题解决。
inheritClass_3占用44字节内存,内存分布如下:
这里写图片描述
inheritClass_1(inheritClass_2)占用28字节,内存分布如下:
这里写图片描述
从内存分布可以看出:
1:虚继承时基类在内存中的地址比派生类的地址大(基类在派生类下面)
2:普通继承(非虚继承)基类的地址比派生类的地址小(基类在派生类上面)
3:菱形继承时,如果被继承的类都是虚继承与基类,那么基类会被合并。从而消除二义性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值