1、声明多继承派生类的方法
1.1、概念
当一个派生类具有多个基类时,这种派生方法称为多基派生或多继承。
1.2、声明
声明具有多个基类的派生类与声明单基派生类的形式相似,只需要将要继承的多个基类使用逗号分隔即可。
例如:已经声明了类X和类Y,可以声明多重继承的派生类Z。
class Z:public X,private Y{ //类 Z公有继承了类 X,私有继承了类 Y
派生类Z中新增的数据成员和成员函数
};
声明多继承派生类的一般形式如下:
class 派生类名:继承方式1 基类名1,…,继承方式n 基类名n{
派生类新增的数据成员和成员函数
};
默认的继承方式是private
1.3、访问
在多继承中,公有继承和私有继承对于基类成员在派生类中的访问属性与单继承的规则相同。
示例代码如下:
#include<iostream>
using namespace std;
class A{ //声明基类 A
public:
void setA(int x)
{
i=x;
}
void showA()
{
cout<<"i="<<i<<endl;
}
private:
int i;
};
class B{ //声明基类 B
public:
void setB(int y)
{
j=y;
}
void showB()
{
cout<<"j="<<j<<endl;
}
private:
int j;
};
class C:public A,private B{ //声明派生类 C,公有继承了类 A,私有继承了类 B
public:
void setC(int x,int y)
{
k=x;
setB(y);
}
void showC()
{
showB();
cout<<"k="<<k<<endl;
}
private:
int k;
};
int main()
{
C obj;
obj.setA(11); //成员函数 setA()在类 C中仍是公有成员
obj.showA(); //成员函数 showA()在类 C中仍是公有成员
obj.setC(22,33); //成员函数 setC()在类 C中是公有成员
obj.showC(); //成员函数 showC()在类 C中是公有成员
return 0;
}
运行结果:
i=11
j=33
k=22
——在上面的代码示例中,根据派生的规则,类A的公有成员在类C中仍是公有成员,类B的公有成员在类C中成为私有成员。所以,在主函数中对类A的公有成员函数setA()的访问是正确的,因为在类C中它仍是公有成员;对类B的成员函数setB()的访问是错误的,因为类B的成员函数setB()在类C中已经成为私有成员,不能直接访问。
1.4、二义性
对基类成员的访问必须是无二义性的
在上面的代码例子中,输出结果的函数是showA()和showC()是无二义性的。在下面的例子中是存在二义性的。
class X{
public:
int f();
};
class Y{
public:
int f();
int g();
};
class Z:public X,public Y{
public:
int g();
int h();
};
当定义类Z的对象obj时:
obj.f();
用下面的方式访问f()是存在二义性的:
obj.f();
因为计算机不知道调用的是类X的f(),还是类Y的f()。
使用成员名限定可以消除二义性
例如上面的例子:
obj.X::f();
obj.Y::f();
就可以正确调用想要调用的类中的函数。
2、多继承派生类的构造函数与析构函数
2.1、定义
多继承派生类的构造函数的定义形式与单继承时的构造函数定义形式相似,只是在初始表中包含多个基类的构造函数。多个基类的构造函数之间用","分隔。
多重继承构造函数定义的一般形式如下:
派生类名(参数总表):基类名1(参数表1),…,基类名n(参数表n)
{
派生类新增成员的初始化语句
}
(1)、与单继承派生类构造函数相同,多重继承派生类构造函数必须同时负责该派生类所有基类构造函数的调用。
(2)、多继承构造函数的调用顺序与单继承构造函数调用顺序相同,遵循先调用基类的构造函数,再调用对象成员的构造函数,最后调用派生类构造函数的原则。
(3)、处于同一层次的各个基类构造函数的调用顺序,取决于声明派生类时所指定的各个基类的顺序,与派生类构造函数中所定义的成员初始化列表的各项顺序没有关系。
(4)、析构函数调用顺序与构造函数相反。