继承
继承的本质意义是复用(不用写就有)
父类的某些东西可以直接使用
eg.
但是注意 : 被继承的成员是新的成员,不是共用同一个成员(实例化的成员变量不同)
但是调用的函数是同一个函数
继承基类成员访问方式的变化(重点)
private访问
" 在派生类中不可见 " 的意思是 : 不管类外还是类里面都不能访问
(自己的访问限定符private是类外面不能用,但是类里面可以用)
private的本质是不想被子类继承(不能被子类访问)
父类的私有对子类不可见
但是,子类可以间接使用父类的私有,即调用父类的成员函数来间接使用
基类和派生类的赋值兼容转换
对于基类和派生类而言,与一般的类型转换不同,转换中间不会产生临时变量
基类和派生类的赋值兼容转换只限于公有继承(父类有的子类都有)
转换规则
继承中的作用域
目前学过的域及其作用:
这里fun的关系是隐藏(函数重载的前提是在同一个作用域,但是两个fun在不同类域)
派生类的构造,析构和拷贝
子类的内置成员根据编译器来判断将内置类型变为0还是不处理
子类的自定义成员调用自定义类型的构造
将父类看作一个整体去调用父类的构造(把整个父类当作一个成员),但是只能调用父类的默认构造
构造函数初始化时是先初始化父类再初始化子类
析构的时候一定要先子后父
友元和静态成员
友元关系不会被子类继承
单继承和多继承
但是多继承存在一定的问题
eg.
多继承的二义性和数据冗余
会产生数据冗余和二义性的多继承也被叫做菱形继承
为了解决数据冗余,C++多加了一个关键字virtual
即使用虚继承
虚继承的底层
但是实践中最好避免使用菱形继承
继承和组合
eg.
尽量优先使用对象组合而非类继承
如果符合is-a关系就用继承
否则就用组合,来降低耦合度,方便维护代码
多态
虚函数
虚函数的重写
子类中有一个与基类完全相同的函数(父类的该函数为虚函数),称子类的虚函数重写了基类的虚函数
( 普通的函数相同构成隐藏 )
注意:只要父类的该函数是虚函数,子类进行重写,就符合虚函数的重写(重写就是特殊的隐藏)
注意 : 重写只会重写函数的实现 , 不影响函数的参数的缺省值
普通调用(看函数内部的代码调用的是谁的函数)
多态调用(根据函数传入的参数的类型不同来选择不同的函数)
例外
c++对析构函数进行了特殊处理,将析构函数的名称统一为destructor
这样就自然符合了多态,避免了析构函数调用错误
eg.
上述情况如果没有多态,就会导致Student开的空间却调用person的析构函数
override和final
override可以检查虚函数是否被重写
final可以用于修饰虚函数,使他无法被重写
重载 , 覆盖(重写) , 隐藏(重定义)的区别
抽象类和纯虚函数
eg.
多态的原理
虚函数表
含有虚函数的类中至少有一个指针, 用来指向虚函数表, 虚函数表中存储着类中的虚函数的地址
虚表的本质是一个函数指针数组, 虚表的地址存放在对象的前四个字节(不同的对象共享同一个虚表)(虚表存在于常量区代码段)
可以通过强制类型转换来获取虚表的地址
eg.
多态调用的原理就是 : 动态确认地址(运行时确定地址) (动态绑定)(根据给的参数不同来调用对应的参数), 根据传入的对象类型进入虚表中查找地址并调用
但是普通函数是静态绑定(无论给的参数是什么都只调用原函数)
eg.
对于多态,基类存在func1, func2两个虚函数,会将两个虚函数存在虚函数表中
派生类对func1进行重写,同样会将虚函数存入虚函数表,但是会将func1的地址换成重写过后的地址,而func的地址不变
标签:调用,函数,继承,子类,多态,C++,父类,重写 From: https://blog.csdn.net/2301_80006788/article/details/140272613