前言

C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数;
形成多态必须具备三个条件:

1.必须存在继承关系;
2.继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字 virtual 声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);
3.存在基类类型的指针或者引用,通过该指针或引用调用虚函数。

一、虚函数与纯虚函数

虚函数
是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错

纯虚函数
若在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。纯虚函数声明如下:virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。

二、示例

新建一个目录 09_polymorphism_example,编辑一个09_polymorphism_example.cpp 内容如下。

1 #include <iostream>
2 #include <string>
3 using namespace std;
4
5 /* 定义一个动物类 */
6 class Animal
7 {
8 public:
9 virtual void run() {
10 cout<<"Animal 的 run()方法"<<endl;
11 }
12 };
13
14 /* 定义一个狗类,并继承动物类 */
15 class Dog : public Animal
16 {
17 public:
18 void run() {
19 cout<<"Dog 的 run()方法"<<endl;
20 }
21 
22 };
23
24 /* 定义一个猫类,并继承动物类 */
25 class Cat : public Animal
26 {
27 public:
28 void run() {
29 cout<<"Cat 的 run()方法"<<endl;
30 }
31 
32 };
33
34 int main()
35 {
36 /* 声明一个 Animal 的指针对象,注:并没有实例化 */
37 Animal *animal;
38 /* 实例化 dog 对象 */
39 Dog dog;
40 /* 实例化 cat 对象 */
41 Cat cat;
42 
43 /* 存储 dog 对象的地址 */
44 animal = &dog;
45 /* 调用 run()方法 */
46 animal->run();
47 
48 /* 存储 cat 对象的地址 */
49 animal = &cat;
50 /* 调用 run()方法 */
51 animal->run();
52 return 0;
53 }

第 9 行、第 18 行和第 28 行,都有一个 run()方法。其中我们可以看到基类 Animal 类的 run()方法前面加了关键字 virtual。这样让基类 Animal 类的 run()方法变成了虚函数。在这个例子里我们可以知道虚函数是 C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。简单的来说,上面的实例是基类 Animal 声明了一个指针 animal。然后通过基类的指针来访问 Dog 类对象与 Cat 类的对象的 run()方法,前提是基类的 run()方法必须声
明为虚函数,如果不声明为虚函数,基类的指针将访问到基类自己的 run()方法。

第 44 行和第 49 行,可以理解是 animal 指针实例化的过程。当基类的 run()方法定义成虚函数,编译器不静态链接到该函数,它将链接到派生类的 run()方法,进行实例化。

然后编译运行