继承方式
public继承
基类的公有和保护成员在派生类中仍然是公有和保护成员,可以由派生类的成员函数来访问,派生类对象可以访问公有的成员;
基类的私有成员,派生类的成员函数与派生类对象都无法访问
private继承
在私有继承方式下,基类所有的非私有成员,在派生类中一律变成派生类的私有成员,派生类只能通过它的成员函数来访问,派生类对象不能访问;
基类的私有成员,在派生类中不可见,只能由基类的成员函数来访问
protected 继承
在保护继承方式下,基类的非私有成员,在派生类中都变成保护成员,这些成员可以被派生类的成员函数访问,但不能被派生类对象访问,基类的私有成员仍然在派生类中不可见
利用保护继承方式,既可以实现成员的隐藏,又可以方便类家族中派生类的访问
赋值兼容规则
赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员,而且所有成员的访问控制属性也和基类完全相同。
1>派生类的对象可以赋值给基类对象。
2>派生类的对象可以初始化基类的引用。
3>派生类对象的地址可以赋给指向基类的指针。
多继承
继承构造函数
假设派生类想要使用基类的构造函数,须要在构造函数中显式声明
格式
struct A{A(int i){}};struct B:A{B(int i):A(i),d(i){}// 初始化列表部分,格式:基类名(参数表), 数据成员(值)int d;};
多继承构造和析构函数的顺序
按照数据成员定义顺序:
在实例化子类的时候,对象会先回溯到父类的构造函数,然后才能调用自己的构造函数。在析构的时候,与构造顺序相反。
虚基类
派生类的构造函数
对基类成员和子对象成员的初始化必须在成员初始化列表中进行,
新增普通数据成员可以在初始化列表中进行初始化,也可以在构造函数体中进行赋值。
派生类构造函数执行顺序是:先调用基类的构造函数,如果有子对象随后调用子对象的构造函数,最后调用派生类的构造函数。
例子
class A //基类{public:A(int x):a(x){ cout << "基类A" << endl; }private:int a;};class S //子对象类{public:S(int y):s(y){ cout << "子对象类S" << endl; }private:int s;};class B: public A //派生类{public:B(int x,int y,int z):objS(y),A(x),b(z){cout << "派生类B" <<endl;}private:S objS; //子对象成员int b;};int main(){B obj(1,2,3);return 0;}
例子
#include <iostream> // 编译预处理命令#include <string> // 编译预处理命令#include <string.h> // 编译预处理命令using namespace std; // 使用命名空间std// 声明人类Personclass Person{protected:string name; // 姓名int age; // 年龄string sex; // 性别public:Person(const string &pName = "无名氏", int pAge = 18, const string &pSex = "未知性别"):name(pName),age(pAge),sex(pSex){}void Show() const{cout<<"姓名:"<<name<<endl;cout<<"年龄:"<<age<<endl;cout<<"性别:"<<sex<<endl;}};// 声明教师类Teacherclass Teacher: virtual public Person{protected:string title; // 职称public:Teacher(const string &tName = "无名氏", int tAge = 28, const string &tSex = "未知性别", const string &tTitle = "未知职称")// 构造函数Person(tName, tAge , tSex ) ,title(tTitle){}void Show() const{/********* Begin *********/cout<<"姓名:"<<name<<endl;cout<<"年龄:"<<age<<endl;cout<<"性别:"<<sex<<endl;cout<<"职称:"<<title<<endl;/********* End *********/}};// 声明干部类Cadreclass Cadre: /* Begin */ virtual public Person/* End */ // Person为公有虚基类{protected:string post; // 职务double wage;public:// 公有函数Cadre(const string &cName = "无名氏", int cAge = 38, const string &cSex = "未知性别", const string &cPost = "未知职务", double cWage = 8000)// 构造函数/* Begin */:Person(cName, cAge , cSex ) ,post(cPost),wage(cWage){}void Show() const // 显示相关信息,显示格式请参考“预期输出”{/********* Begin *********/cout<<"姓名:"<<name<<endl;cout<<"年龄:"<<age<<endl;cout<<"性别:"<<sex<<endl;cout<<"职务:"<<post<<endl;cout<<"工资:"<<wage<<"元"<<endl;/********* End *********/}};// 声明教师干部类TeacherCadreclass TeacherCadre: public Teacher, public Cadre{public:// 公有函数TeacherCadre(const string &tcName = "无名氏", int tcAge = 46, const string &tcSex = "未知性别", const string &tcTitle = "未知职称", const string &tcPost = "未知职务", double tcWage = 8000)// 构造函数Person(tcName, tcAge , tcSex ),Teacher(tcName, tcAge , tcSex,tcTitle),Cadre(tcName, tcAge , tcSex,tcPost,tcWage){}void Show() const // 显示相关信息,显示格式请参考“预期输出”{/********* Begin *********/cout<<"姓名:"<<name<<endl;cout<<"年龄:"<<age<<endl;cout<<"性别:"<<sex<<endl;cout<<"职称:"<<title<<endl;cout<<"职务:"<<post<<endl;cout<<"工资:"<<wage<<"元"<<endl;/********* End *********/}};

