文章目录
21天学通C++第8版(二)
第11章 多态
多态的一些性质
-
多态(Polymorphism)是面向对象语言的一种特征,让您能够以类似的方式处理不同类似的对象。
-
为什么需要多态
#include <iostream> using namespace std; class Fish { public: void Swim() { cout << "Fish swims!" << endl; } }; class Tuna:public Fish { public: // override Fish::Swim void Swim() { cout << "Tuna swims!" << endl; } }; void MakeFishSwim(Fish& InputFish) { // calling Fish::Swim InputFish.Swim(); } int main() { Tuna myDinner; // calling Tuna::Swim myDinner.Swim(); // sending Tuna as Fish MakeFishSwim(myDinner); return 0; }
输出:
Tuna swims! Fish swims!
Tuna 类以公有方式继承了 Fish 类,它还覆盖了方法 Fish::Swim( )。在 main( )中,
直接调用了 Tuna::Swim( ),并将 myDinner (其类型为 Tuna)作为参数传递给了 MakeFishSwim( ),而该函数将其视为 Fish 引用。换句话说,虽然传入的是 Tuna 对象,MakeFishSwim(Fish&)也将其视为 Fish,进而调用 Fish::Swim。第 2 行输出表明,虽然传入的是 Tuna对象,但得到的却是 Fish 的输出。理想情况下,用户希望 Tuna 对象表现出金枪鱼的行为,即便通过 Fish 参数调用 Swim( )时亦如此。换句话说,调用 inputFish.Swim( )时,用户希望执行的是 Tuna::Swim( )。要实现这种多态行为—让 Fish 参数表现出其实际类型(派生类 Tuna)的行为,可将 Fish::Swim( )声明为虚函数。
-
override(覆盖)和overload(重载)的区别
- 重载Overload:在同一个类中,允许存在一个以上的同名函数,只要他们的参数个数或者参数类型不同即可。与返回值类型无关,只看参数列表 。
- 重写Override:表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中定义的方法,这相当于把父类中定义的那个完全相同的方法给覆盖掉了,这也是面向对象编程的多态的一种表现。
使用虚函数实现多态行为
-
通过使用关键字 virtual,可确保编译器调用覆盖版本。也就是说,如果Swim( )被声明为虚函数,则将参数 myFish(其类型为 Fish&)设置为一个Tuna对象时, myFish.Swim( )将执行Tuna::Swim( )
#include <iostream> using namespace std; class Fish { public: virtual void Swim() { cout << "Fish swims!" << endl; } }; class Tuna:public Fish { public: // override Fish::Swim void Swim() { cout << "Tuna swims!" << endl; } }; class Carp:public Fish { public: // override Fish::Swim void Swim() { cout << "Carp swims!" << endl; } }; void MakeFishSwim(Fish& InputFish) { // calling Swim InputFish.Swim(); } int main() { Tuna myDinner; Carp myLunch; // sending Tuna as Fish MakeFishSwim(myDinner); // sending Carp as Fish MakeFishSwim(myLunch); return 0; }
输出结果:
Tuna swims! Carp swims!
-
虚函数的工作原理–虚函数表
#include <iostream> using namespace std; class SimpleClass { int a, b; public: void DoSomething(){ } }; class Base { int a, b; public: virtual void DoSomething(){ } }; int main() { cout << "sizeof(SimpleClass) = " << sizeof(SimpleClass) << endl; cout << "Sizeof(Base) = " << sizeof<