目录
1.基类和派生类
一个派生类只从一个基类派生,这称为单继承(single inheritance)。一个派生类不仅可以从一个基类派生,也可以从多个基类派生,也就是说,一个派生类可以有两个或多个基类,这称为多重继承(multiple inheritance)。
关于基类和派生类的关系,可以表述为:派生类是基类的具体化,而基类则是派生类的抽象。基类综合了派生类的公共特征,派生类则在基类的基础上增加某些特性,把抽象类变成具体的、实用的类型。
在声明派生类时,一般还应当自己定义派生类的构造函数和析构函数,因为构造函数和析构函数是不能从基类继承的。派生类时基类定义的延续。可以先声明一个基类,在此基类中只提供某些最基本的功能,然后在声明派生类时加入某些具体的功能,形成适用于某一特定应用的派生类。提供对基类声明的延续,将一个抽象的基类转化成具体的派生类。因此,派生类是抽象基类的具体实现。
2.派生类成员的访问属性
在派生类中,对基类的继承方式可以有public、private和protected三种。不同的继承方式决定了基类成员在派生类中的访问属性。
(1)公用继承
在定义一个派生类时将基类的继承方式指定为public的,称为公用继承,用公用继承方式建立的派生类称为公用派生类,其基类称为公用基类。采用公用继承方式时,基类的公用成员和保护成员在派生类中仍然保持其公用成员和保护成员的属性,而基类的私有成员在派生类中并没有称为派生类的私有成员,它仍然是基类的私有成员,只有基类的成员函数可以引用它,而不能被派生类的成员函数引用,因此就成为派生类中的不可访问的成员。
(2)私有继承
在声明一个派生类时将基类的继承方式指定为private的,称为私有继承,用私有继承方式建立的派生类称为私有派生类,其基类称为私有基类。私有基类的公用成员和保护成员在派生类的访问属性中相当于派生类的私有成员,即派生类的成员函数能访问它们,而在派生类外不能访问它们。私有基类的私有成员在派生类中称为不可访问的成员,只有基类的成员函数可以引用它们。
(3)保护成员和保护继承
由protected声明的成员称为受保护的成员(简称保护成员),保护成员不能被类外访问,但可以被派生类的成员函数引用(这点与私有成员不同)。在声明一个派生类时将基类的继承方式指定为protected的,称为保护继承,用保护继承方式建立的派生类称为保护派生类,其基类称为受保护的基类(简称保护基类)。保护继承的特点是:保护基类的公有成员和保护成员在派生类中都成了保护成员,其私有成员仍为基类私有,也就是把基类原有的公有成员也保护起来,不让类外任意访问。
(4)多级派生时的访问属性
如果类A为基类,类B是类A的派生类,类C是类B的派生类,则类C也是类A的派生类。类B称为类A的直接派生类,类C称为类A的直接派生类。类A是类B的直接基类,是类C的间接基类。在多级派生的情况下,各成员的访问属性原则不变。
3. 简单的派生类的构造函数
构造函数的主要作用是对数据成员初始化。基类的构造函数是不能被继承的,在声明派生类时,派生类并没有把基类的构造函数继承过来。因此,对继承过来的基类成员的初始化工作也要由派生类的构造函数承担。所以在设计派生类的构造函数时,不仅要考虑派生类所增加的数据成员的初始化,还应当考虑基类的数据成员的初始化。也就是说,希望在执行派生类的构造函数时,使派生类的数据成员和基类的数据成员同时都被初始化。解决方法是:在执行派生类的构造函数时,调用基类的构造函数。
任何派生类都包含基类的成员,简单的派生类只有一个基类,而且只有一级派生(即只有直接派生类,没有间接派生类),在派生类的数据成员中不包含基类的对象(即子对象,后续补充)。
派生类的构造函数的一般形式为:派生类构造函数名(总参数表):基类构造函数名(参数表){派生类中新增数据成员的初始化语句} 或者完全采用参数初始化表方式:派生类构造函数名(总参数表):基类构造函数名(参数表),参数初始化表{}。下面是一个简单的派生类的构造函数的实例。
#include<iostream>
#include<string>
using namespace std;
class Student{ //声明基类Student
public:
Student(int num,string name,char sex){ //定义基类构造函数
this->num = num;
this->name = name;
this->sex = sex;
}
~Student(){} //基类析构函数
protected: //基类保护部分
int num;
string name;
char sex;
};
class StudentSon:public Student{ //声明公用派生类StudentSon
public: //派生类的公用部分
StudentSon(int num,string name,char sex,int age,string addr):Student(num,name,sex){
this->age = age; //在函数体中只能对派生类新增的数据成员初始化
this->addr = addr;
}
void show(){
cout << "num:" << num << endl;
cout << "name:" << name << endl;
cout << "sex:" << sex << endl;
cout << "age:" << age << endl;
cout << "addr:" << addr << endl;
}
~StudentSon(){} //派生类构造函数
private: //派生类的私有部分
int age;
string addr;
};
int main()
{
StudentSon stud1(10010,"Zhangsan",'f',19,"Beijing Road");
StudentSon stud2(10011,"Lisi",'m',22,"Shanghai Road");
stud1.show(); //输出第一个学生的数据
stud2.show(); //输出第二个学生的数据
return 0;
}
顺序:在建立一个派生类对象时,派生类构造函数先调用基类构造函数,再执行派生类构造函数本身(即派生类构造函数的函数体)。对于上例,先初始化num、age、sex,然后再初始化age和addr。在派生类对象释放时,先执行派生类析构函数~StudentSon(),再执行其基类析构函数~Student()。