继承与派生
继承与派生概述:
继承与派生是同一个过程从不同的角度看:
保持已有类的特性而构成新类的过程称为继承
在已有类的基础上新增自己的特性而产生新类的过程称为派生
被继承的已有类成为基类(父类)base class
派生出的新类称为派生类(子类)derived class
直接参与派生出某类的基类成为直接基类
基类的基类甚至更高层的基类称为间接基类
继承的目的:
实现设计与代码的重用,充分利用原有的类
派生的目的:
当新的问题出现,原有程序无法解决,需要对原有程序进行改造
单继承时派生类的定义: class 派生类名:继承方式 基类名{
成员声明;
}
例子:
class Derived: public Base{
public:
Derived();
~Derived();
};
多继承时派生类的定义:
class 派生类名:继承方式1 基类名1, 继承方式2 基类名2, 。。。。。 {
成员声明;
};
例子:
class Derived: public Base1, private Base 2{
public:
Derived();
~Derived();
};
派生类的构成:
吸收基类的成员,(默认情况下,派生类包含全部基类中除了构造函数之外的所有成员,C++11规定可以使用using语句继承基类构造函数)
改造基类成员,(如果派生类中声明了一个和某基类成员同名的新成员, 派生的新成员就隐藏或覆盖了外层同名成员)
添加新的成员
继承方式简介:
三种继承方式:公有(public ),私有(private),保护继承(protected)
重点写一下保护成员:在派生类中可以作为public,在基类中类似private。(也就是说,如果想要把基类中的私有成员给派生类用,但是却又不想将此成员作为public成员,可以设定为protected成员,这样可以达到派生类可以访问的效果)
私有继承:将除了私有成员的其他成员转换成派生类的私有成员
派生类的构造函数:
派生类新增成员:派生类定义构造函数初始化;
继承来的成员:自动调用基类构造函数进行初始化;
派生类的构造函数需要给基类的构造函数传递参数。
单继承时构造函数的定义语法:
派生类名::派生类名(基类所需的形参,本类成员所需的形参):
基类名(参数表),本类成员初始化列表
{
//其他初始化;
};
多继承且有对象成员时派生的构造函数定义语法:
派生类名::派生类名(形参表):
基类名1(参数),基类名2(参数),..., 基类名n(参数),本类成员(含成员对象成员)初始化列表
{
//其他初始化;
};
派生类的复制构造函数:
若派生类没有定义复制构造函数:
编译器会在需要的时候生成隐含的复制构造函数
派生类的析构函数:
析构函数不被继承,派生类如果需要,要自行声明析构函数,析构时应先执行本类成员的析构,然后析构从基类继承过来的成员
访问从基类继承的成员:(被隐藏的基类成员)
当派生类与基类中有相同的成员,基类中的同名成员会被隐藏,若想访问被隐藏的成员需要利用作用域:
例如:
class father 里面有一个display(),class son里面也有一个display(),father里面的display()会被隐藏,若想访问father里面的display()可以在前面加上类域:
son s;
s.display(); //这里的display是son里面的display()
s.father::display(); // 这里的display是father里面的display()
菱形继承
为了避免二义性:需要将每一类的成员前加上其类名
为了避免数据冗余:就需要虚继承:
虚基类
虚基类声明:
用virtual说明基类继承方式
例如:class B1: virtual public B
注意:在第一级派生就应该设计为虚基类
当存在虚基类的时候,图中的Derived类的构造函数需要把最原始的Base()也加上,因为中间经过的是虚继承