继承与派生的概念
用户用已有的类去定义一个新类,新类将拥有原来类的全部特性,原有类叫做基类(父类),新产生的类叫做派生类(子类)。派生类拥有基类的特性叫做继承,基类产生派生类的过程叫做派生。
继承方式
公有继承、私有继承、保护继承。
单继承:在类的层次击结构中,除最顶层的基类外,其他派生类有且只有一个父类。
多继承:派生类具有两个及两个以上的直接基类
继承性质
- 可传递性:类A派生出类B,类B还可以派生出类C。(类A成为类B的直接基类,称为类C的间接基类)
- 不允许循环:类A派生出类B,类B不能再派生出类A。
\ | 基类属性 | public | protected | private |
---|---|---|---|---|
继承方式 | \ | \ | \ | \ |
public | \ | public | protected | 不可访问 |
protected | \ | protected | protected | 不可访问 |
private | \ | private | private | 不可访问 |
派生类的实现
class 派生类名称:继承方式1 基类1,继承方式2 基类2.... (不显示继承方式,默认私有继承)
{
private:
public:
protected:
}
派生类构造函数的定义
派生类名(参数总表):基类名1(参数表1),....,基类名m(参数表m),成员对象1(成员对象参数表1),....,成员对象m(成员对象参数表m)
{
派生类新增成员的初始化
}
单继承的构造与析构
派生类构造函数的调用顺序
- 调用基类构造函数
- 调用内嵌成员对象的构造函数,调用顺序按照定义的顺序(没有内嵌成员就跳过)
- 派生类自己的构造函数
析构函数调用顺序与构造函数相反
多继承的构造函数调用顺序
- 调用各级类的构造函数,调用顺序按照被继承时的声明顺序
- 调用内嵌成员对象构造函数,成员对象的构造函数的调用顺序按照在派生类中声明的顺序
- 调用派生类的构造函数
析构析构函数调用顺序与构造函数相反
二义性问题
如果多个基类中拥有同名的成员,那么,派生类在继承各个基类的成员之后,当我们调用该派生类的成员时,由于该成员标识符不唯一,出现二义性,编译器是无法识别到底应该调用哪个成员。这种由于多继承而引起的对类的某个成员访问出现不唯一的情况称为二义性。
#include<iostream>
using namespace std;
class A
{
public:
void show()
{
cout<<"A"<<endl;
}
};
class B
{
public:
void show()
{
cout<<"B"<<endl;
}
};
class C:public A,public B
{
public:
void Show()//解决二义性问题
{
A::show();
B::show();
}
};
int main()
{
C c;
//c.show();//出现二义性
c.Show();//正确
}
类型兼容
条件:公有派生
一个派生类对象可以作为基类对象使用的情况叫做类型兼容(类型赋值兼容或类型适应)
三种情况
- 派生类对象可以赋值给基类对象
- 派生类对象可以初始化基类的引用
- 派生类对象的地址可以赋值给指向基类的指针