C++——多重继承(菱形继承)

MI(多重继承)

上图

很好理解,B,C有着一样的祖先,D的祖先又是B,C像棱形一样。

MI有时候很方便,但是带来的是很多难以发现的问题

1.派生类中多继承一份基类

2.同名函数的处理

3.类方法递增导致类方法重复

4.基类中的构造函数怎么办

下面是解决办法和一些基本规则

主要的设计难点:类内组件如何用保护权限构建。

其他的语法都很简单,编程学的不是语法,而是学的思想

#include <iostream>
#define ENDL cout << endl;
using namespace std;
class Base
{
private:
    int base;
public:
    explicit Base(int _base) : base(_base) {}
    void show() const
    {
        cout << base;
    }
protected:
    void data() const
    {
        cout << base;
    }
};
//语法
//用virtual关键字继承,这种继承不像是虚函数中的virtual,他可以说是关键字重载
//不用virtual 将会导致AB中出现两份Base对象
class A :virtual public Base
{
private:
    int a;
public:
    A(int _base, int _a) : Base(_base), a(_a) {}
    void show()
    {
        Base::show();
        cout << a;
    }

public:
    void data() const
    {
        cout << a;
    }
};

class B : virtual public Base
{
private:
    int b;
public:
    B(int _base, int _b) : Base(_base), b(_b) {}
    void show() const
    {
        Base::show();
        cout << b;
    }
public:
    void data() const
    {
        cout << b;
    }
};
//Base 是虚基类,虽然其中没有虚函数
class AB :public A,public B
{
private:
    int ab;
public:
    AB(int _base, int _a, int _b, int _ab) : Base(_base) , A(_base, _a), B(_base,_b), ab(_ab){}
    void show()
    {
        A::show();
        B::show();
        cout << ab;
    }
    void showPlus()
    {
        Base::data();
        AB::data();
        cout << ab;
    }
protected:
    void data()
    {
        A::data();
        B::data();
    }
};
int main()
{
    AB temp = AB(0, 1, 2, 3);
    //不能直接访问show会出现二义性,即编译器不知道用哪个基类中的show方法
    //应使用作用域解析符号,或者在派生类中重定义
    //当然重定义会带来很多问题,我们也有解决的办法
    temp.Base::show();
    ENDL
    temp.A::show();
    ENDL
    temp.B::show();
    //派生类中重定义
    //这将会导调用两次基类中show()方法
    ENDL
    temp.show(); //或者显式的调用 temp.AB::show();
    ENDL
    temp.showPlus();
    return 0;
}

这时候protected权限的作用就来了,我么又想能够访问让派生类访问提供的data组件,又不想让类外访问到data组件,那么用保护权限就可以完美的解决这个问题

关于构造函数:

我们看一看构造函数的语法形式

explicit Base(int _base) : base(_base) {}

A(int _base, int _a) : Base(_base), a(_a) {}

B(int _base, int _b) : Base(_base), b(_b) {}

AB(int _base, int _a, int _b, int _ab) : Base(_base) , A(_base, _a), B(_base,_b), ab(_ab){}

使用的是列表初始化,其实我们可以看到在Base, A, B中的构造函数形式就是简单的列表初始化,但在AB中 我们要用到新的构造函数规则

对于虚基类,构造函数的自动传递(即有派生类调用基类的构造函数)将不起作用;在自动传递信息时,将通过两条不同的途径自动传递给基类对象。为了避免这种冲突,C++在基类是虚的时,禁止通过中间类自动传递给基类。因此必须在初始化派生类之前,显式的调用基类中的构造函数,尽管中间类中的语法看似让基类初始化,但实际上并不起作用。如果没有显式的调用,编译器将自动调用默认构造函数。

总结:多重继承问题多,先是基类成员和方法继承了多份,这个只要用virtual。主要避免二义性,加上作用域解析符。类内组件提供用portected,向下继承避免重复调用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值