C++类继承基础6——多重继承与虚基类

多重继承的原理

多重继承(multiple inheritance)是指从多个直接基类中产生派生类的能力。

多重继承的派生类继承了所有父类的属性。

在面向对象的编程中,多重继承意味着一个类可以从多个父类继承属性和方法。

就像你有一杯混合果汁,它是由多种水果榨取而来的,每种水果都为这杯果汁带来了独特的味道和营养。

假设我们有三个类:Animal(动物)、Bird(鸟类)和Swimmer(游泳者)。

Animal类有eat()方法,Bird类有fly()方法,而Swimmer类有swim()方法。

现在,我们想要创建一个新的类叫做SeaBird(海鸟),它既能飞,又能游泳,还像其他动物一样吃东西。这时候,我们就可以使用多重继承来实现这个需求。


多重继承

多重继承的声明格式如下

class 派生类名:访问说明符 基类1名,访问说明符 基类名2...
{
}

或者
struct 派生类名:访问说明符 基类1名,访问说明符 基类名2...
{
}

在派生类的派生列表中可以包含多个基类

class A1:public A{...};
class AB:public A,public B{...};

每个基类包含一个可选的访问说明符。一如往常,如果访问说明符被忽略掉了,则关键字class对应的默认访问说明符是private,关键字struct对应的是public。

class A1:A{};
//和class A1:private A{}等价
//和struct A2:private A{}等价


struct A2:A{};
//和struct A2:public A{}等价
//和class A1:public A{}等价

和只有一个基类的继承一样,多重继承的派生列表也只能包含已经被定义过的类,而且这些类不能是final的。

对于派生类能够继承的基类个数,C++没有进行特殊规定;但是在某个给定的派生列表中,同一个基类只能出现一次。

class A1:A,A{}//这是错误的

多重继承的派生类从每个基类中继承状态

在多重继承关系中,派生类的对象包含有每个基类的子对象。

就是说一个派生类对象不仅包含自己特有的部分,还包含它的基类部分

我们举个例子

class A{
int a;
}
class A1:A{
int b;
}

一个A1对象不仅含有它特有的部分(变量b),还含有它的基类部分(变量a) 

派生类构造函数初始化所有基类 

构造一个派生类的对象将同时构造并初始化它的所有基类子对象。

与从一个基类进行的派生一样,多重继承的派生类的构造函数初始值也只能初始化它的直接基类

class A1
{public:
	A1(int a_):a(a_){}
	int a;
};
class A2
{
public:
	int b;
	A2(int b_):b(b_){}
};
class AA1 :A1,A2
{
	int c;
	AA1(int a_,int b_,int c_):A1(a_),A2(b_),c(c_){}//显式地初始化所有基类
};
class A1
{public:
	A1(int a_):a(a_){}
	A1(){}
	int a;
};
class A2
{
public:
	int b;
	A2(int b_):b(b_){}
};
class AA1 :A1,A2
{
	int c;
	AA1(int a_,int b_,int c_):A2(b_),c(c_){}//隐式的使用A1的默认构造函数来初始化a
};

 多重继承派生类的构造函数

多重继承派生类的构造函数形式与单一继承时的构造函数形式基本相同,只是在派生类的构造函数初始化列表中调用多个基类构造函数。

一般形式为:

派生类名(形式参数列表):基类名1(基类1构造函数实参列表),基类名2(基类2构造函数实参列表),
                      ...,
                      成员对象名1(子对象1属类构造函数实参列表),
                      ...,
                      派生类初始化列表
{
    派生类初始化函数体
}

派生类的构造函数初始值列表将实参分别传递给每个直接基类。

其中基类的构造顺序与派生列表中基类的出现顺序保持一致,而与派生类构造函数初始值列表中基类的顺序无关。


其调用顺序是:

  1. 调用基类构造函数,各个基类按定义时的次序先后调用;
  2. 调用成员对象构造函数,各个子对象按声明时的次序先后调用;
  3. 执行派生类初始化列表;
  4. 执行派生类初始化函数体;

例:多重继承举例

#include<iostream> 
using namespace std; 

class Base1 {
    private:
        int b1;
    public:
        Base1() {
            b1=0;
            cout<<"默认构造Base1:"<<"b1="<<b1<<endl;
        }
        Base1(int i) {
            b1=i;
            cout<<"构造Base1:"<<"b1="<<b1<<endl;
        }
};

class Base2 {
    private:
        int b2;
    public:
        Base2() {
            b2=0;
            cout<<"默认构造Base2:"<<"b2="<<b2<<endl;
        }
        Base2(int j) {
            b2=j;
            cout<<"构造Base2:"<<"b2="<<b2<<endl;
        }
};

class Base3 {
    public:
        Base3() {
            cout<<"默认构造Base3:"<<endl;
        }
};

class Derive : public Base1,public Base2,public Base3 {
    private:
        Base1 memberBase1;
        Base2 memberBase2;
        Base3 memberBase3;
    public:
        Derive() {
            cout<<"默认构造函数Derive."<<endl; 
        }
        Derive(int a,int b,int c,int d): Base1(a),Base2(b),memberBase1(c),memberBase2(d) {
            cout<<"构造Derive."<<endl;
        }
};

int main()
{
    cout<<endl<<"创建派生类对象obj1:"<<endl;
    Derive obj1;
    cout<<endl<<"创建派生类对象(1,2,3,4):"<<endl;
    Derive obj2(1,2,3,4);
    return 0;
}



运行结果:

创建派生类对象obj1:
默认构造Base1:b1=0//基类默认构造函数,下面2个也是
默认构造Base2:b2=0
默认构造Base3:
默认构造Base1:b1=0//成员对象的构造函数,下面2个也是
默认构造Base2:b2=0
默认构造Base3:
默认构造函数Derive,//派生类默认构造函数

创建派生类对象(1.2.3.4):
构造Base1:b1=1   //基类构造函数,下面2个也是
构造Base2:b2=2
默认构造Base3:
构造Base1:b1=3  //成员对象的构造函数,下面2个也是
构造Base2:b2=4
默认构造Base3:
构造Derive.     //派生类构造函数

继承的构造函数的易错点

在C

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值