1、虚函数、覆盖、多态安全
虚函数:在定义时添加virtual关键字的成员函数,叫虚函数函数
覆盖:在子类中实现与父类中虚函数相同的函数,那么子类中的成员函数会覆盖父类中的成员函数this
不一样于隐藏,隐藏是在父子类之间名字相同的标识符,只要不够成覆盖,就是隐藏。子类会隐藏父类中的同名函数spa
多态:若是子类中的成员函数对父类中的成员函数进行了覆盖,那么当一个指向子类的父类指针或引用了子类的父类引用,在调用此同名函数时会调用子类中的函数,而不是父类中的虚函数,这种语法现象叫多态。设计
多态的意义在于同一种类发出同一种调用而产生不一样的反映指针
2、覆盖、重载、隐藏的条件对象
覆盖(重写):继承
a、不在同一做用域,分别在基类和派生类接口
b、函数名、参数、返回值相同内存
c、基类函数必须有virtual关键字
d、访问修饰符能够不一样
重载:
a、在同一做用域下
b、函数名相同,参数不一样
c、返回值能够不一样
隐藏:
a、在不一样做用域中
b、函数名相同
c、在基类和派生类中只要不构成覆盖就是隐藏
3、多态的条件
一、派生类必须重写基类的虚函数。
二、经过基类指针或引用调用基类的虚函数(该虚函数派生类必需要重写)
三、当指针或引用已经构成多态时,此时调用成员所传的this指针再调用成员函数时也构成多态
四、在子类的构造函数执行前会先调用父类的构造函数,若是调用被覆盖的虚函数,因为子类还没构造完成,所以只能是调用父类中的虚函数构造函数在进入函数体执行时,类中看得见的资源已经所有构造完成
五、在子类的析构函数执行完成后会再调用父类的析构函数,若是调用被覆盖的虚函数,因为子类已经开始析构完成已经不能算是完整的子类了,所以只能调用父类中的虚函数
4、纯虚函数和抽象类
一、纯虚函数
class A
{
public:
virtual void test(void) = 0;
virtual void test(void) const = 0;
};
a、纯虚函数不须要被实现,若是非要实现也不能在类中,必需要在类外(虚函数)
b、纯虚函数若是想调用必须在子类中覆盖,而后以多态的方式调用
二、抽象类
成员函数中有纯虚函数的叫抽象类,这种类不能建立对象。
若是子类继承了抽象类,则必须把父类中的纯虚函数覆盖了,不然他也变成了抽象类不能被实例化
所以抽象类只能以指针或引用的方式指向子类来调用非纯虚函数
三、纯抽象类
全部的成员函数都是纯虚函数,这种类叫纯抽象类
面向对象的四大特性:抽象、封装、继承、多态
纯抽象类是类封装的过程,同时抽象类也能够当作一个统一的接口
6、虚函数表
一、什么是虚函数表,当一个类中有虚函数时,编译器会为这个函数分配一个专门记录这些的虚函数表,在类中会有一个隐藏的指针成员指向这张表
二、如何证实这张表存在
有虚函数的类会比没有虚函数的类(相同的)多4字节,还会添加补齐和对其
三、一个类只有一张虚函数表,全部对象共享一张虚函数表
四、通常对象的前4字节是指向虚函数表的指针
7、动态类型绑定(多态)
一、当使用父类指针或引用指向子类时,编译器并无当即生成调用函数的指针,而是生成了一段代码,用于检查指针指向的真正的对象是什么类型
二、在代码真正运行时才经过对象的指针找到指向虚函数的成员指针
三、再经过成员指针访问到虚函数表,再从中找到调用的函数地址
四、使用多态会产生额外的一些代码和调用,所以使用多态会下降代码的执行速度
9、虚析构
一、若是经过父类指针或引用指向子类对象,当使用delete释放对象时,此时只能调用父类的析构函数,若是子类中使用new/malloc申请了内存资源,那么将致使内存泄漏
二、解决方法就是把父类的析构函数设置为虚函数
三、在设计类时若是析构函数什么都须要作,编译器也会生成一个空的析构函数,但这样会让继承它的子类会有安全隐患
四、最好把全部的析构函数都设置为虚函数