概念
完成某个行为时,不同对象的所在的不同状态
形成多态的条件:
1、必须通过基类的指针或者引用调用虚函数
2、基类必须是虚函数,并且派生类对基类虚函数重写
多态分为静态多态和动态多态
静态多态(静态绑定或前期绑定):函数重载和函数模板的实例化,也称为编译期间的多态
动态多态(动态绑定或前期绑定):继承、虚函数重写、实现的多态,也称为运行时的多态
为什么不能是父类对象指针或者引用?
子类给父类拷贝赋值时,不会拷贝虚表
虚函数
用virtual修饰的类成员函数被称为虚函数
注意
1、在虚函数声明时加virtual,在类外不可以加virtual
2、static跟virtual不能同时使用
虚函数的virtual与之前继承中隐藏是同一个关键字,但是没有任何关系,这里的virtual是为了虚函数的重写,继承中的隐藏是为了解决二义性和数据冗余的问题
虚函数重写(覆盖)
重写条件:
1、作用域分别在基类和派生类
2、函数返回类型、函数名、参数都相同(参数相同是参数类型相同)
3、两个函数都是虚函数
class A
{
public:
virtual void f()
{
cout << "A::f()" << endl;
}
};
class B : public A
{
public:
virtual void f()
{
cout << "B::f()" << endl;
}
};
void func(A& p)//函数调用父类引用
{
return p.f();
}
int main()
{
B b;
func(b);
return 0;
}
注意:重写之后如果不用基类指针或者引用去访问,就只能访问到基类的函数
协变:函数返回类型不同,即基类返回基类指针或者引用,子类返回子类指针或者引用(了解)
析构函数重写
只要基类的析构函数是虚函数,派生类函数定义,那么就构成重写
为什么函数名不同却构成了虚函数重写?
因为类的析构函数被处理成destructor这个名字
为什么处理成这个名字?
希望能够构成重写,重写后就能够多态调用,而不是普通调用
C++11final和override
final修饰父类之后就不能被重写
class A
{
public:
virtual void f() final
{
cout << "A::f()" << endl;
}
};
override在子类检查是否构成重写
class B : public A
{
public:
virtual void f() override
{
cout << "B::f()" << endl;
}
};