C++多態

多態的概念 :關於多態,好幾種說法,好的壞的都有,分別說一下:
1 指同一個函數的多種形態。
個人認爲這是一種高手中的高手喜歡的說法,對於一般開發人員是一種差的不能再差的概念,簡直是對人的誤導,然人很容易就靠到函數重載上了。

以下是個人認爲解釋的比較好的兩種說法,意思大體相同:
2多態是具有表現多種形態的能力的特徵,在OO中是指,語言具有根據對象的類型以不同方式處理之,特別是重載方法和繼承類這種形式的能力。
這種說法有點繞,仔細想想,這纔是C++要告訴我們的。

3多態性是允許你將父對象設置成爲和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。多態性在Object Pascal和C++中都是通過虛函數(Virtual Function) 實現的。

官方,也是更準確的對多態作用的描述:
多態性使得能夠利用同一類(基類)類型的指針來引用不同類的對象,以及根據所引用對象的不同,以不同的方式執行相同的操作。把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作(也就是可以調用子對象中對父對象的相關函數的改進方法)。



C++中的多態(雖然多態不是C++所特有的,但是C++中的多態確實是很特殊的)分爲靜多態和動多態(也就是靜態綁定和動態綁定兩種現象),靜動的區別主要在於這種綁定發生在編譯期還是運行期,發生在編譯期的是靜態綁定,也就是靜多態;發生在運行期的則是動態綁定,也就是動多態。  靜多態可以通過模板和函數重載來實現(之所說C++中的多態主要還是因爲模板這個東西),下面舉兩個例子: 1)函數模板 template <typename T> T max(const T& lsh, const T& rhs)  {        return (lsh > rhs) ? lsh : rhs; } 返回兩個任意類型對象的最大值(對象),前提是該類型能夠使用>運算符進行比較,並且返回值是bool類型。 使用: int a = 3; int b = 4; cout << max(a, b) << endl; float c = 2.4; float d = 1.2; cout << max(c, d) << endl; 輸出結果爲:          4                 2.4 這種綁定發生在編譯期,這是由於模板的實例化是發生在編譯期的,即在編譯時編譯器發現你調用max(a, b)時就自動生成一個函數 int max(const int& lsh, const int& rhs)  {        return (lsh > rhs) ? lsh : rhs; } 即將所有的T替換成int; 當你調用max(c, d)時就自動生成一個函數 float max(const float& lsh, const float& rhs) {         return (lsh > rhs) ? lsh : rhs; } 之所以說開始的函數定義是函數模板,就是因爲他就像個模子似的,你可以用鋁作爲原料也可以用石膏或者銅。 2)函數重載: int max (int a, int b) {      return (a > b) ? a : b; } int max (int a, int b, int c) {      return max(max(a, b), c); } 兩個函數名稱一樣,參數類型或個數不完全相同,返回值一樣(這個不重要)。 使用: int a = 3, b = 4, c = 5; cout << max(a, b) << endl; cout << max(a, b, c) << endl; 輸出結果爲:          4                 5 確定函數的過程也發生在編譯器,當你使用max(a, b),編譯器發現只有兩個參數,那麼就調用只有兩個參數的函數版本,當使用max(a, b, c)時,編譯器則使用有3個參數的版本。 通過上面的兩個例子,你還可以使用更爲方便的模板函數重載: template <typename T> T max(const T& lsh, const T& rhs)  {        return (lsh > rhs) ? lsh : rhs; }  template <typename T> T max(const T& a, const T& b, const T& c) {       return max(max(a, b), c); } 使用 float a = 3.6, b = 1.2, c = 7.8; cout << max(a, b, c) << endl; 輸出:        7.8 通過參數個數和類型,編譯器自動生成和調用對應得函數版本!  動多態則是通過繼承、虛函數(virtual)、指針來實現。 class A { public:     virtual void func() const {          coust << “A::func()” << endl;     } }  class B : public A { public:      virtual void func() const {          coust << “B::func()” << endl;     } } 使用: A a* = B(); a->func(); 輸出:      B::func() 編譯期是不調用任何函數的,編譯器編譯到a->func()時只是檢查有沒有語法問題,經過檢查沒有。編譯器並不知道調用的是A版本的func()還是B版本的func(),由於a是一個指向B對象的指針,所以a只知道它指向的是一個A類型(或者能轉換成A類型)的對象。通常集成體系就說明了(由於是公有繼承)B是一種A。在運行期,a要調用a所指向對象的func()函數,就對它指向的對象下達調用func()的命令,結果a所指向的是一個B對象,這個對象就調用了自己版本(B版)的func()函數,所以輸出時B::func()  總結: 在編譯期決定你應該調用哪個函數的行爲是靜態綁定(static-binding),這種現象就是靜多態。 在運行期決定應該調用哪中類型對象的函數的行爲是動態綁定(dynamic-binding),這種現象就是動多態!  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章