面向對象的三大特性是封裝,繼承和多態,本文主要介紹C++里的多態特性
在編譯器把函數或模板連接生產執行代碼的過程中,有兩種聯編方式,一種是靜態聯編,另外一種是動態聯編,
靜態聯編是在編譯階段就把函數連接起來,就可以確定調用哪個函數或者模板,而動態聯編是指在程序運行時才能確定函數和實現的連接,才能確定調用哪個函數
根據聯編的方式我可以把多態(函數多種形態)分成兩種,靜態多態和動態多態,網上有些資料有四種,多出了宏多態和函數多態,但我個人認為這兩種應該屬於靜態多態
動態多態
主要通過繼承和虛函數實現,父類指針或者引用能夠指向子類對象,調用子類的虛函數,所有在編譯時是無法確定調用哪個虛函數,每個子類都維護着一張虛函數表,
程序執行時查詢虛函數表來確定調用哪個虛函數;
1 #include <iostream> 2 using namespace std; 3 4 class Base 5 { 6 public: 7 virtual void Print() = 0; 8 virtual ~Base(){} 9 }; 10 11 class child_1 : public Base 12 { 13 public: 14 void Print() 15 { 16 cout << "child_1 Print function" << endl; 17 } 18 ~child_1() 19 { 20 cout << "child_1 destructor function" << endl; 21 } 22 }; 23 24 class child_2: public Base 25 { 26 public: 27 void Print() 28 { 29 cout << "child_2 Print function" << endl; 30 } 31 ~child_2() 32 { 33 cout << "child_2 destructor function" << endl; 34 } 35 }; 36 37 int main() 38 { 39 Base *p = new child_1; //父類指針指向子類對象 40 p->Print(); 41 delete p; //記住釋放,否則內存泄露 42 p = new child_2; 43 p->Print(); 44 delete p; 45 p = NULL; 46 return 0; 47 }
存在這樣的多態特性,所有最好是把類的析構函數定義成virtual類型,否則在釋放時無法調用析構函數
靜態多態
使用的是靜態聯編方式,在編譯時函數和函數的實現就關聯在一起,主要是通過重載和模板實現,在宏多態中,是通過定義變量,編譯時直接把變量替換,實現宏多態.
1 #include <iostream> 2 using namespace std; 3 4 //宏多態;a,b可以不同類型 5 #define sum(a,b) ((a) + (b)) 6 7 class Base 8 { 9 public: 10 void Print() //不需要定義為虛函數 11 { 12 cout << "base Print() functions" << endl; 13 } 14 void Print(int val) //重載,根據參數列表不同實現函數多態 15 { 16 cout << "base Print(int) functions" << endl; 17 } 18 }; 19 20 class child : public Base 21 { 22 public: 23 void Print() //不需要定義為虛函數 24 { 25 cout << "child Print() functions" << endl; 26 } 27 void Print(int val) //重載,根據參數列表不同實現函數多態 28 { 29 cout << "child Print(int) functions" << endl; 30 } 31 32 }; 33 34 template<typename T> 35 void func(T &p) 36 { 37 p.Print(); 38 p.Print(1); 39 } 40 41 int main() 42 { 43 Base base ; 44 child ch; 45 int a = 23, b = 19; 46 double fa = 13.32, fb = 29.36; 47 func(base); 48 func(ch); 49 50 cout << sum(a,b) << endl; 51 cout << sum(fa,fb) << endl; 52 return 0; 53 }