目录
1. 多态的构成条件
在继承中要构成多态还有两个条件:
- 必须通过基类的指针或者引用调用虚函数
- 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
2. 多态调用特点
- 普通调用:调用函数的对象类型是谁,就调这个类型的函数
- 多态调用:调用 指针或引用 指向的对象,指向父类调用父类的函数,指向子类调用子类的函数
3. 虚函数
虚函数:即被virtual修饰的类成员函数称虚函数(virtual只能修饰成员函数)
3.1 虚函数的重写
虚函数的重写 又叫做 虚函数的覆盖
继承中虚函数的重写:子类继承的是父类虚函数的接口,子类重写的是子类虚函数的实现
-
父子继承关系的两个虚函数,三同(函数名/参数/返回)
-
三同(函数名/参数/返回)的例外:协变—>返回值可以不同,但是返回值必须都是父子类关系的指针或者引用
-
派生类重写的虚函数可以不加virtual(建议都加上)
3.2 析构函数必须为虚函数的情况
为了使 父子类的 析构函数是虚函数(虚函数有三同特点),
析构函数统一会被处理成destructor
- 即:delete p; 的本质其实是:
p->destrutor() + operator delete ( p );
析构函数必须为虚函数的情况 即使用new的情况,如下:
class Person {
public:
virtual A* BuyTicket()
{
cout << "Person买票-全价" << endl;
return nullptr;
}
virtual ~Person()
{
cout << "~Person()" << endl;
}
};
class Student : public Person {
public:
virtual B* BuyTicket()
{
cout << "Student买票-半价" << endl;
return nullptr;
}
~Student()
{
cout << "~Student()" << endl;
}
};
int main()
{
Person* p = new Person;
// 析构是虚函数,才能正确调用析构函数
// p->destrutor() + operator delete(p)
delete p;
p = new Student;
// p->destrutor() + operator delete(p)
delete p;
return 0;
}
4. 重载、覆盖(重写)、隐藏(重定义)的对比
5. C++11 override 和 final
final:
- final 修饰类,类不能被继承
- final 修饰虚函数,虚函数不能被重写(final 若修饰函数,只能修饰虚函数)
class Car
{
public:
virtual void Drive() final {}
};
class Benz :public Car
{
public:
virtual void Drive() {cout << "Benz-舒适" << endl;}
};
override:
- 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。
class Car{
public:
virtual void Drive(){}
};
class Benz :public Car {
public:
virtual void Drive() override {cout << "Benz-舒适" << endl;}
};
6. 抽象类
6.1 概念
- 在虚函数的后面写上 =0 ,则这个函数为纯虚函数。
- 包含纯虚函数的类叫做抽象类(也叫接口类)
- 抽象类不能实例化出对象。派生类继承后也不能实例化出对象
- 只有重写纯虚函数,派生类才能实例化出对象。
- 纯虚函数
1、间接强制去派生类去重写
2、抽象类-不能实例化出对象
class Car
{
public:
virtual void Drive() = 0;
};
class Benz :public Car
{
public:
virtual void Drive()
{
cout << "Benz-舒适" << endl;
}
};
class BMW :public Car
{
public:
virtual void Drive()
{
cout << "BMW-操控" << endl;
}
};
void Test()
{
Car* pBenz = new Benz;
pBenz->Drive(); //这里没有用到多态,因为这是子类调用虚函数
Car* pBMW = new BMW;
pBMW->Drive(); //这里没有用到多态,因为这是子类调用虚函数
}
6.2 接口继承和实现继承
- 普通函数的继承是一种实现继承
- 虚函数的继承是一种接口继承
7. 多态的原理
7.1 虚函数指针 和 虚函数表
- 若类内有虚函数,类内就会多1个指针,该指针指向虚函数表,对象中的这个指针我们叫做虚函数表指针
- 一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表,虚函数表其实就是一个函数指针数组