49-多态的概念和意义
函数重写回顾
1、父类中被重写的函数依然会继承给子类
2、子类中重写的函数将覆盖父类中的函数
3、通过作用域分辨符(::)可以访问到父类中的函数
多态的概念和意义
面向对象中期望的行为:
1、根据实际的对象类型判断如何调用重写函数
2、父类指针(引用)指向:(1)父类对象则调用父类中定义的函数(2)子类对象则调用子类中定义的重写函数
面向对象中的多态的概念:
1、根据实际的对象类型决定函数调用的具体目标
2、同样的调用语句在实际运行时有多种不同的表现形态
C++语言直接支持多态的概念:
1、通过使用virtual关键字对多态进行支持
2、被virtual声明的函数被重写后具有多态特性
3、被virtual声明的函数叫做虚函数
【范例代码】多态的初体验
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent { 7 public: 8 virtual void print() { 9 cout << "I'm Parent." << endl; 10 } 11 }; 12 13 class Child : public Parent { 14 public: 15 void print() { 16 cout << "I'm Child." << endl; 17 } 18 }; 19 20 void how_to_print(Parent* p) { 21 p->print(); // 展现多态的行为 22 } 23 24 int main(int argc, const char* argv[]) { 25 Parent p; 26 Child c; 27 28 how_to_print(&p); // Expected to print: I'm Parent. 29 how_to_print(&c); // Expected to print: I'm Child. 30 31 return 0; 32 }
多态的意义:
1、在程序运行过程中展现出动态的特性
2、函数重写必须多态实现,否则没有意义
3、多态是面向对象组件化程序设计的基础特性
理论中的概念:
♦ 静态联编:在程序的编译期间就能确定具体的函数调用,如函数重载
♦ 动态联编:在程序实际运行后才能确定具体的函数调用,如函数重写
【范例代码】动态联编与静态联编
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent { 7 public: 8 virtual void func() { 9 cout << "void func()" << endl; 10 } 11 12 virtual void func(int i) { 13 cout << "void func(int i) : " << i << endl; 14 } 15 16 virtual void func(int i, int j) { 17 cout << "void func(int i, int j) : " << "(" << i << ", " << j << ")" << endl; 18 } 19 }; 20 21 class Child : public Parent { 22 public: 23 void func(int i, int j) { 24 cout << "void func(int i, int j) : " << i + j << endl; 25 } 26 27 void func(int i, int j, int k) { 28 cout << "void func(int i, int j, int k) : " << i + j + k << endl; 29 } 30 }; 31 32 void run(Parent* p) { 33 p->func(1, 2); // 展现多态的特性 34 // 动态联编 35 } 36 37 int main(int argc, const char* argv[]) { 38 Parent p; 39 40 p.func(); // 静态联编 41 p.func(1); // 静态联编 42 p.func(1, 2); // 静态联编 43 44 cout << endl; 45 46 Child c; 47 48 c.func(1, 2); // 静态联编 49 50 cout << endl; 51 52 run(&p); 53 run(&c); 54 55 return 0; 56 }
【范例代码】江湖恩怨
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Boss { 7 public: 8 int fight() { 9 int ret = 10; 10 11 cout << "Boss::fight() : " << ret << endl; 12 13 return ret; 14 } 15 }; 16 17 class Master { 18 public: 19 virtual int eightSwordKill() { 20 int ret = 8; 21 22 cout << "Master::eightSwordKill() : " << ret << endl; 23 24 return ret; 25 } 26 }; 27 28 class NewMaster : public Master { 29 public: 30 int eightSwordKill() { 31 int ret = Master::eightSwordKill() * 2; 32 33 cout << "NewMaster::eightSwordKill() : " << ret << endl; 34 35 return ret; 36 } 37 }; 38 39 void field_pk(Master* master, Boss* boss) { 40 int k = master->eightSwordKill(); 41 int b = boss->fight(); 42 43 if (k < b) { 44 cout << "Master is killed..." << endl; 45 } else { 46 cout << "Boss is killed..." << endl; 47 } 48 } 49 50 int main(int argc, const char* argv[]) { 51 Master master; 52 Boss boss; 53 54 cout << "Master vs Boss" << endl; 55 56 field_pk(&master, &boss); 57 58 cout << "NewMaster vs Boss" << endl; 59 60 NewMaster newMaster; 61 62 field_pk(&newMaster, &boss); 63 64 return 0; 65 }