多重继承以及菱形继承

多重继承

多重继承

  • 一个派生类具有多个基类
  • 优点,代码复用
class A : public C, public B
{
    
    
    
};

抽象类

具有纯虚函数的类

虚基类

  • virtual 可以修饰成员函数,叫做虚函数
  • virtual修饰继承方式,是虚继承。被虚继承的类,叫做虚基类

派生类虚继承后的内存布局

#include <iostream>
class Base
{
    
    
public:
    Base(int a):ma(a){
    
    
    }

    virtual void show() {
    
    }
private:
    int ma;
};

class Drived : virtual public Base {
    
    
public:
    Drived(int data):Base(data),mb(data){
    
    }
    void show() {
    
    }
private:
    int mb;
};

int main()
{
    
    
    Drived d(10);
}

下图为上述代码类 class Drived的内存分布。

class Drived    size(40):
        +---
 0      | {
    
    vbptr}
 8      | mb
        | <alignment member> (size=4)
        | <alignment member> (size=4)
        +---
20      | (vtordisp for vbase Base)
        +--- (virtual base Base)
24      | {
    
    vfptr}
32      | ma
        | <alignment member> (size=4)
        +---

由于Base为虚基类,所以当Drived虚继承Base的时候,class Drived内存就会如上所示。从Base继承而来的部分,被放在Drived内存末尾,并且在内存首部使用了一个vbptr,该指针指向存放于末尾的Base的部分。

菱形继承

解决方式虚继承

实例

class A {
    
    
public:
    A(int data) : a(data) {
    
    
        cout << "A()" << endl;
    }
    ~A()
    {
    
    
        cout << "~A()" << endl;
    }
private:
    int a;
};

class B : virtual public A {
    
    
public:
    B(int data) : A(data)
        , b(data) {
    
    
        cout << "B()" << endl;
    }
    ~B()
    {
    
    
        cout << "~B()" << endl;
    }

private:
    int b;
};

class C : virtual public A {
    
    
public:
    C(int data) : A(data)
        ,c(data) {
    
    
        cout << "C()" << endl;
    }
    ~C()
    {
    
    
        cout << "~C()" << endl;
    }

private:
    int c;
};
class D :public B, public C{
    
    
public:
    D(int data) : A(data)
        ,B(data)
        ,C(data)
        ,d(data) {
    
    
        cout << "D()" << endl;
    }
    ~D() {
    
    
        cout << "~D()" << endl;
    }
private:
    int d;
};
int main()
{
    
    
    D d(10);
}

class D的内存分布

class D size(48):
        +---
 0      | +--- (base class B)
 0      | | {vbptr}
 8      | | b
        | | <alignment member> (size=4)
        | | <alignment member> (size=4)
        | +---
16      | +--- (base class C)
16      | | {vbptr}
24      | | c
        | | <alignment member> (size=4)
        | | <alignment member> (size=4)
        | +---
32      | d
        | <alignment member> (size=4)
        | <alignment member> (size=4)
        +---
        +--- (virtual base A)
40      | a
        +---

D::$vbtable@B@:
 0      | 0
 1      | 40 (Dd(B+0)A)

D::$vbtable@C@:
 0      | 0
 1      | 24 (Dd(C+0)A)

  • 使用虚继承,虚基类A部分的变量被放置到类D的末尾
  • B、C里面的虚基类部分被替换成vbptr指向A部分
  • 对A进行构造的时候需要在D内部单独构造,而不是经过B、C进行构造

猜你喜欢

转载自blog.csdn.net/weixin_43459437/article/details/143406627