多态
同一行为,不同对象完成时产生的不同状态
多态是在不同继承关系的类对象,去调用同一函数,产生了不同行为。
-
形成条件
- 必须通过基类的指针或者引用调用虚函数
- 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
-
虚函数
被virtual修饰的类成员函数称为虚函数
class Person { public: virtual void display(); };
-
虚函数的重写
虚函数的重写(覆盖): 派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名、参数列表完全相同),则派生类的虚函数重写了基类的虚函数
class Person { public: virtual void display() { cout << "hhh" << endl; } }; class Student { public: virtual void display() { cout << "heihei" << endl; } }; void Func(Person& p) { p.display() }
-
析构函数重写
如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同,违反了重写规则,但是编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一为destructor
class Person { public: virtual ~Person() { cout << "~Person" << endl; } }; class Student : public Person { public: virtual ~Student() { cout << "~student" << endl; } }; void test5() { Person *p1 = new Person; Person *p2 = new Student; delete p1; delete p2; } // 申明基类析构函数为虚函数 实现多态 // delete p2 会调用Student析构
-
override/ final
- final 修饰虚函数,表示该虚函数不能再被继承
- override 检查派生类是否重写了某个基类虚函数,如果没有重写报错
-
重载 覆盖(重写) 隐藏(重定义)的对比
- 重载:函数名相同,参数列表不同,两个函数在同一作用域
- 重写:基类与派生类作用域中且都是虚函数,函数名返回值参数列表都必须相同 析构函数除外,协变除外
- 隐藏:基类与派生类作用域中,函数名相同,但不是虚函数
-
抽象类
在虚函数后面写上=0, 则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(接口类), 抽象类不能实例化。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化对象。纯虚函数规范了派生类必须重写
class Test { public: virtual void display() = 0; }; class child : public Test { public: virtual void display() override { cout << "display" << endl; } }; int main() { Test* t = new child; t->display(); return 0; }
-