1.继承的概念继承是面向对象的三大特性之一。继承可以理解成是类级别的一个复用它允许我们在原有类的基础上进行扩展增加新的功能。当创建一个类时我们可以继承一个已有类的成员和方法并且在原有的基础上进行提升这个被继承的类叫做基类而这个继承后新建的类叫做派生类。用法如下class [派生类名] : [继承类型] [基类名]例如1234567891011classPerson{public:string _name;int_age;};classStudent :publicPerson{protected:string _stuNum;};这里的派生类Student就复用了Person的方法和成员并在此基础上扩展补充。2.继承方式继承的方式和类的访问限定符一样分为public(公有继承)private(私有继承) protected(保护继承)三种。不同的继承方式在派生类中继承下来的基类成员的访问权限也不一样。基类的其他成员在子类的访问方式 Min(成员在基类的访问限定符继承方式)备注1.在实际运用中一般使用都是public继承几乎很少使用protetced/private继承也不提倡使用protetced/private继承因为protetced/private继承下来的成员都只能 在派生类的类里面使用实际中扩展维护性不强。2.使用关键字class时默认的继承方式是private使用struct时默认的继承方式是public不过最好显示的写出继承方式。3.基类与派生类的赋值转换派生类可以赋值给基类的对象、指针或者引用这样的赋值也叫做对象切割。例如上面的Person类和Student类这种赋值只能是派生类赋给基类但需要割掉多出来的成员例如_ stuID而基类对象不能赋给派生类。基类的指针可以强制类型转换赋值给派生类的指针 如:12345678910intmain(){Person p1;Student s1;Person* hPtr1 s1;//指向派生类对象Person* hPtr2 p1;//指向基类对象Student* pPtr (Student*)hPtr1;//没问题Student* pPtr (Student*)hPtr2;//有时候没有问题但是会存在越界风险return0;}小结1.派生类可以赋值给基类的对象、指针或者引用2.基类对象不能赋值给派生类对象3.基类的指针可以通过强制类型转换赋值给派生类的指针。**但是必须是基类的指针是指向派生类对象时才是安全的否则会存在越界的风险。**这里基类如果是多态类型可以使用RTT的dynamic_cast来进行识别后进行安全转换。4.作用域与隐藏隐藏隐藏也叫做重定义当基类和派生类中出现重名的成员时派生类就会将基类的同名成员给隐藏起来然后使用自己的。但是隐藏并不意味着就无法访问可以通过指明基类作用域来显式访问隐藏成员。)1234567891011121314151617181920212223classPerson{public:voidf(intage){cout 姓名 _name endl;cout 年龄 _age endl;}protected:string _name;int_age;};classStudent :publicPerson{public:voidf(){Person::f(32);//需显式调用f函数cout 学号 _stuNum endl;}private:string _stuNum;};例如这里的f( 就构成了隐藏同时这里还有个需要注意的问题在基类与派生类中同名的方法并不能构成重载因为处于不同的作用域中。而只要满足方法名相同就会构成隐藏。5.派生类的默认成员函数在每一个类中都会有6个默认的成员函数这些函数即使我们自己不去实现编译器也会帮我们实现。这里有两点需要注意笔试题常考1.构造函数拷贝构造operator三种情况都要调用父类对应的构造函数/拷贝构造/operator进行对父类的成员变量的初始化并且倘若父类没有默认的构造函数的时候比如父类写了带参的构造函数我们就要显式调用Person参数…,Person::operator(参数…)构造函数显示调用派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函 数则必须在派生类构造函数的初始化列表阶段显示调用。12345Student():People(){cout Student() endl;}拷贝构造显示调用建议拷贝构造都用显示调用不然免不了出现子类拷贝构造当中调用了父类的构造函数的情况(因为拷贝构造也是构造在初始化列表处对于子类而言父类相当于一个自定义类型对象子类会调用父类的构造函数对父类的资源进行初始化。)12345Student(constStudent s):People(s){cout Student(const Student s) endl;}派生类的operator必须要调用基类的operator完成基类的复制。12345678Student operator(constStudent s){cout Student operator (const Student s) endl;if(this! s){Person:: operator(s);}}析构函数由于编译器会将析构函数的名字处理成destructor因此派生类和基类的析构函数会构成隐藏关系故若要派生类要调用基类的析构函数那么需要显式调用但是编译器会默认在派生类的析构函数调用结束后调用基类的析构函数这样就析构两次了。123456789~Person(){cout ~Person() endl;}~Student(){Person:: ~Person();cout ~Student() endl;}在派生类中基类的析构函数会被隐藏虽然它们这里的名字不同但是为了实现多态 它们都会被编译器重命名为destructor。在调用子类的构造函数时我们是先调用父类的构造函数后对子类的成员进行构造。由先构造后析构的顺序所以我们是在析构函数当中析构子类的资源析构函数调用完后编译器自动帮我们调用父类的析构函数。6.友元与静态成员1.友元友元关系是不会继承的如果子类要使用父类的友元则子类自己也要将其定义为友元。2.静态成员基类定义了static静态成员无论继承了多少次派生了多少子类静态成员在这整个继承体系中有且只有一个。静态成员不再单独属于某一个类亦或者是某一个对象而是属于这一整个继承体系。7.菱形继承与虚继承首先简单介绍下单继承、多继承的概念单继承一个子类只有一个直接父类时称这个继承关系为单继承多继承一个子类有两个或以上直接父类时称这个继承关系为多继承菱形继承菱形继承是多继承的一种特殊情况下面简单举例介绍下菱形继承及其带来的二义性问题123456789101112131415161718classHuman{public:int_age;};classStudent :publicHuman{public:int_stuNum;};classTeacher :publicHuman{public:int_teaNum;};classAssistant :publicTeacher,publicStudent{};哦豁菱形继承这个关系感受到了吧