1、继承
在一个已经存在的类的基础上建立一个新的类。通过继承,一个新建子类从已有的父类那里获得父类的特性。从另一角度看,从已有的类(父类)产生一个新的子类,称为类的派生。
单继承:一个派生类只从一个基类派生
多重继承:一个派生类有两个或多个基类。
派生类是基类的具体化,而基类是派生类的抽象。
2、声明派生类的一般形式:
class 派生类名:[继承方式] 基类名
{
派生类新增加的成员
}
继承的方式:public、private、protected
(1) 公有继承(public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。
(2)私有继承(private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
(3)保护继承(protected)
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
举例:
公有继承
class Base //父类
2 {
3 private:
4 int _priB;
5 protected:
6 int _proB;
7 public:
8 int _pubB;
9 } ;
10 class Derived: public Base //子类,继承自base,继承类型为公有继承
11 {
12 private:
13 int _d_pri;
14 protected:
15 int _d_pro;
16 public:
17 void funct()
18 {
19 int d;
20 d=_priB; //error:基类中私有成员在派生类中是不可见的
21 d=_proB; //ok: 基类的保护成员在派生类中为保护成员
22 d=_pubB; //ok: 基类的公共成员在派生类中为公共成员
23 }
24 int _d_pub;
25 } ;
私有继承:
class C :private Base //基类Base的派生类C(私有继承)
{
public:
void funct()
{
int c;
c=_priB; //error:基类中私有成员在派生类中是不可见的
c=_proB; //ok:基类的保护成员在派生类中为私有成员
c=_pubB; //ok:基类的公共成员在派生类中为私有成员
}
};
保护继承:
class E :protected Base //基类Base的派生类E(保护继承)
{
public:
void funct()
{
int e ;
e=_priB; //error:基类中私有成员在派生类中是不可见的
e=_proB; //ok:基类的保护成员在派生类中为保护成员
e=_pubB; //ok:基类的公共成员在派生类中为保护成员
}
};
3、派生类的构造函数
构造函数的主要功能是对数据成员的初始化。用户在声明基类时可以不定义构造函数,系统会自动设置一个默认的构造函数,不执行任何操作。如果需要对类中的成员初始化,应自己构造初始函数。
基类的构造函数是不能继承的,在声明派生类的时,派生类并没有把基类的构造函数继承过来,为了使执行派生类的构造函数的同时,使派生类的数据成员和基类的数据成员同时初始化,需要在执行派生类的构造函数时,同时调用基类的构造函数。
(1)派生类的构造函数的一般形式:
派生类构造函数名(总形式参数表列):基类构造函数名(实际参数表列){派生类中新增数据成员初始化语句}
如:Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s),age(a),addr(ad){}
对于派生类中增加的成员数据的初始化也可以不再初始化表中进行初始化,而是在函数体中进行:
Student1(int n,string name,char s,int a,string ad):Student(n,nam,s)
{
age=a;
addr=ad;
}
(2)派生类构造函数的执行顺序:
先调用基类构造函数,再执行派生类构造函数本身(即派生类构造函数的函数体)。
class Base
{
protected:
Base(){cout<<'A';)
};
class Derived:public Base
{
public:
Derived(char c)
{
cout<<c;
}
};
int main()
{
Derived d('B');
return 0;
}
上面执行的结果为AB.
所以无论在派生类的构造函数中是否明确写出调用基类的构造函数,基类的构造函数时一定要执行的。
(3)有子对象的派生类
类中的数据成员还可以包含对象
子对象:即对象中的对象,类的成员数据是另一个类的对象
一般格式:
派生类构造函数名(总形式参数表列):基类构造函数名(实际参数表列),子对象名(实际参数表列)
{派生类中新增数据成员初始化语句}
如:
Student1 (int n,string name,int n1,string nam1,int a,string ad):Student(n,nam),monitor(n1,nam),age(a),addr(ad){}
执行顺序:
先调用基类的构造函数,对基类的数据成员初始化。
在调用子对象的构造函数,对子对象的数据成员初始化。
再执行派生类构造函数本身,对派生类数据成员的初始化。
(4)多层派生时的构造函数
一个类不仅可以派生出一个派生类,派生类还可以继续派生,形成派生的层次结构。
原则:每一层的派生类只会调用上一层的直接的构造函数,不关心任何其他的包括上上层基类的构造函数。
4、派生类的析构函数
在派生时,派生类是不能继承基类的析构函数的,也需要派生类的析构函数去调用基类的析构函数。在派生类中可以根据需要定义自己的析构函数,用来对派生类中所增加的成员进行清理工作。基类的清理工作仍然由基类的析构函数负责。在执行派生类的析构函数时,系统会自动的调用基类的析构函数和子对象的析构函数,对基类和子对象进行清理。
5、多重继承
c++允许一个派生类同时继承多个基类,称为多重继承。
(1)定义形式
class D:public A,private B,protected C
{类 D 新增加的成员}