- 父類中被重寫的函數依然會繼承給子類
- 子類中重寫的函數將覆蓋父類中的函數
- 經過做用域分辨符 (::) 能夠訪問到父類中的函數
void code() { Child c; Parent* p = &c; c.Parent::print(); // 從父類中繼承 c.print(); // 從子類中重寫 p->print(); // 從父類中定義 }
思考:
爲何要重寫父類中的成員函數呢?ios
答:
父類中提供的成員函數版本不能知足需求編程
面向對象中指望的行爲函數
- 根據實際的對象類型判斷如何調用重寫函數
父類指針( 引用 )指向組件化
- 父類對象則調用父類中定義的函數
- 子類對象則調用子類中定義的函數
面向對象中多態的概念spa
- 根據實際的對象類型決定函數調用的具體目標
- 一樣的調用語句在實際運行時有多種不一樣的表現形態
C++ 語言直接支持多態的概念設計
- 經過 virtual 關鍵字對多態進行支持
- 被 virtual 聲明的函數被重寫後具備多態性
- 被 virtual 聲明的函數叫作虛函數
#include <iostream> using namespace std; class Parent { public: virtual void print() { cout << "I'm Parent." << endl; } }; class Child : public Parent { public: void print() // 由於繼承, 子類中 void print() 也是虛函數 { cout << "I'm Child." << endl; } }; void how_to_print(Parent* p) { p->print(); // 展示多態的行爲 } int main() { Parent p; Child c; how_to_print(&p); // Expected to print: I'm Parent how_to_print(&c); // Expected to print: I'm Child return 0; }
輸出: I'm Parent. I'm Child.
多態的意義3d
- 在程序運行過程當中展示出動態的特性
- 函數重寫必須多態實現,不然沒有意義
- 多態是面向對象組件化程序設計的基礎特性
理論中的概念指針
靜態聯編code
在程序的編譯期間就能肯定具體的函數調用對象
- 如: 函數重載
動態聯編
在程序實際運行後才能肯定具體的函數調用
- 如: 函數函數重寫
#include <iostream> using namespace std; class Parent { public: virtual void func() { cout << "void func()" << endl; } virtual void func(int i) { cout << "void func(int i) : " << i << endl; } virtual void func(int i, int j) { cout << "void func(int i, int j)" << "(" << i << ", " << j << ")" << endl; } }; class Child : public Parent { public: void func(int i, int j) { cout << "void func(int i, int j) : " << i + j << endl; } void func(int i, int j, int k) { cout << "void func(int i, int j, int k) : " << i + j + k << endl; } }; void run(Parent* p) { p->func(1, 2); // 展示多態的行爲 // 動態聯編 } int main() { Parent p; p.func(); // 靜態聯編 p.func(1); // 靜態聯編 p.func(1, 2); // 靜態聯編 cout << endl; Child c; c.func(1, 2); // 靜態聯編 cout << endl; run(&p); run(&c); return 0; }
輸出: void func() void func(int i) : 1 void func(int i, int j)(1, 2) void func(int i, int j) : 3 void func(int i, int j)(1, 2) void func(int i, int j) : 3
#include <iostream> #include <string> using namespace std; class Boss { public: int fight() { int ret = 10; cout << "Boss::fight() : " << ret << endl; return ret; } }; class Master { public: virtual int eightSwordKill() { int ret = 8; cout << "Master::eightSwordKill() : " << ret << endl; return ret; } }; class NewMaster : public Master { public: int eightSwordKill() { int ret = Master::eightSwordKill() * 2; cout << "Master::eightSwordKill() : " << ret << endl; return ret; } }; void field_pk(Master* master, Boss* boss) { int k = master->eightSwordKill(); int b = boss->fight(); if( k < b ) { cout << "Master is killed... " << endl; } else { cout << "Boss is killed... " << endl; } } int main() { Master master; Boss boss; cout << "Master vs Boss" << endl; field_pk(&master, &boss); cout << "NewMaster vs Boss" << endl; NewMaster newMaster; field_pk(&newMaster, &boss); return 0; }
輸出: aster vs Boss Master::eightSwordKill() : 8 Boss::fight() : 10 Master is killed... NewMaster vs Boss Master::eightSwordKill() : 8 NewMaster::eightSwordKill() : 16 Boss::fight() : 10 Boss is killed...
- 函數重寫只可能發生在父類與子類之間
- 根據實際對象的類型肯定調用的具體函數
- virtual 關鍵字是 C++ 中支持多態的惟一方式
- 被重寫的虛函數可表現出多態的特性
以上內容參考狄泰軟件學院系列課程,請你們保護原創!