概念
生活中 :子继承父遗留给的物质或精神产业代码中 :子类继承父类 , 可以降低代码的冗余度 , 提高代码复用率
名词
子类继承父类父类派生子类
注意
一个父类可以派生多个子类多个子类可以属于同一个父类一个类可以继承多个父类
继承方式
作用
约束子类使用父类成员的范围private 将父类中所有成员变为 private 修饰protected 父类私有还是私有 , 父类受保护的还是受保护的 , 父类公共的变为受保护的public 父类成员访问是什么在子类中就是什么 ( 推荐使用 )
继承语法
语法
class 子类名:继承方式 父类名,继承方式 父类名2{//编写子类成员};
子类中调用父类构造函数
语法
子类名 ( 形参列表 ): 父类名 ( 形参 1, 形参 2,..){}
子父类对象转换
1.子类对象转换为父类对象
自动转换无风险如 :Dog d;Anim& a = d;
2.父类对象转换为子类对象
强制转换有风险如 :Cat c;Anim& a = c;Dog& d = (Dog&) a;( 有风险 )Cat& c2 = (Cat&) a;
注意
在强制转换时有风险 , 需要自身判断是否可以转换
继承关系中同名成员的区分
子父类成员变量名相同
子类对象.成员变量名 子类成员变量子类对象 . 父类名 ::成员变量名 类成员变量
子父类成员函数名相同
子类对象 . 成员函数名 (实参列表) 子类成员函数子类对象 . 父类名 :: 成员函数名 ( 实参列表) 父类成员函数
不能继承
父类构造函数父类拷贝构造父类析构operator=
继承关系中的构造与析构顺序
父子类中
父构子构子析父析
父子孙类中
父构子构孙构孙析子析父析
子类成员变量为其他类的对象
父类构造成员构造子类构造子类析构成员析构父类析构
多继承
概念
一个子类有多个父类
示例
#include <iostream>using namespace std;class Ma{public:char name[50];};class Lv{public:char name[50];};class LuoZi:public Ma,public Lv{public:char name[50];};int main(int argc, char const *argv[]){LuoZi lz;lz.Ma::name;lz.Lv::name;lz.name;return 0;}
菱形继承
概述
A 派生 B,C,D 多继承 B,C, 此时菱形继承此时 D 中将有两份 A 的成员
示例
#include <iostream>using namespace std;class Anim{public:char name[50];};class Ma:public Anim{};class Lv:public Anim{};class LuoZi:public Ma,public Lv{};int main(int argc, char const *argv[]){LuoZi lz;lz.Ma::name;lz.Lv::name;return 0;}
虚继承
作用
解决多继承或菱形继承得到多份
语法
当类继承时在继承方式前加 virtual注意A 派生 B,C,D 继承 B,C, 给 B,C 继承 A 时加
示例
#include <iostream>#include <string.h>using namespace std;class Anim{public:char name[50];};class Ma:virtual public Anim{};class Lv:virtual public Anim{};class LuoZi: public Ma, public Lv{};int main(int argc, char const *argv[]){LuoZi lz;strcpy(lz.Ma::name," 骡子 ( 马 )");strcpy(lz.Lv::name," 骡子 ( 驴 )");strcpy(lz.name," 骡子 ");cout << lz.Ma::name << endl;cout << lz.Lv::name << endl;cout << lz.name << endl;return 0;}
没有虚继承前的类图
Anim
Ma
Lv
LuoZi
有虚继承的类图
Anim
Ma
Lv
LuoZi
vbtable: 虚基表vbptr: 虚基指针