因為,我們編寫**時,有的時候,當物件不同時,就需要呼叫不同的函式。在這個時候就需要使用的多型了。
再說類的多型性之前我先來說說物件這個概念。
物件的概念可以分為兩種型別
所謂的靜態型別,就是一般的型別 。。。
而動態型別,舉個例子來說就像是賦值相容規則裡說的
乙個基類物件可以用 派生類物件來賦值;在這裡的這個物件就是動態型別的。
因為只有在執行時呼叫物件時 才知道呼叫的實際上是乙個派生類的物件。。。
多型概念:多型這一特性,用通俗的話來說就是 乙個事物在不同的時候表現為多種狀態。。。。
但是在c++中多型有這更為廣泛的含義
所謂靜態多型,指的是編譯器在編譯期間完成的,編譯器根據函式實參的型別(可能會進行隱式型別轉換),可推
斷出要呼叫那個函式,如果有對應的函式就呼叫該函式,否則出現編譯錯誤。
函式過載,編譯器在編譯時,就已經判斷出引數的型別 ,根據型別的不同來呼叫不同的函式。
模板 ,也如函式過載一般,根據模板引數的不同呼叫函式。
函式過載例子:
關於模板的示例可以看看我之前寫的c++函式模板
動態繫結指的是在程式執行期間(非編譯期)判斷所引用物件的實際型別,根據其實際型別呼叫相應的方法。
在這裡我們動態多型講的主要是 說 虛函式
虛函式使用virtual關鍵字修飾類的成員函式時,指明該函式為虛函式,派生類需要重新實現,編譯器將實
現動態繫結。
下面來舉個虛函式的示例:
class b
};class d:public b
};int main()
**執行結果:
從輸出的結果上我們看出
b.base();//呼叫的是基類的函式
b1->base();//呼叫的是派生類的函式
d.base();//呼叫的是派生類的函式
函式呼叫時b1呼叫的是物件d記憶體,所以呼叫的是派生類的函式;;;;
【動態繫結條件】
1、必須是虛函式
2、通過基類型別的引用或者指標呼叫虛函式
下面說說在多型中 我們可能會遇到幾種函式名相同的情況:
1、函式過載
限定條件為:
1)在同一作用域內;(一定要記住這一點)
2)函式名相同;
3)引數列表相同(引數的順序 ,型別 ,長度)
2、同名隱藏
限定條件為:
1)乙個在基類中,乙個在派生類裡;
2)函式名相同;
3、函式重寫
限定條件為:
1)乙個在基類中,乙個在派生類裡
2)都是虛函式;
3)函式原型相同(函式名,引數,返回值相同)
4、協變
限定條件為:
1)乙個在基類中,乙個在派生類裡
2)都是虛函式
3)函式名相同,引數列表相同
4)函式返回值分別為基類的指標(引用),派生類類的指標(引用)
下面有一段**我們來看看
class b
void test2(int _test)
void test3(int _test)
virtual b* test4(int _test1, int _test2)
};
class d :public b
virtual void test2(int _test)
void test3(int _test)
virtual d* test4(int _test1, int _test2)
};上述**中
test1()屬於函式重寫
test2()屬於虛函式
test3()屬於同名隱藏
test4()屬於協變
所謂純虛函式
在成員函式的形參後面寫上=0,則成員函式為純虛函式。
包含純虛函式的類叫做抽象類(也叫介面類),抽象類不能例項化出物件。純虛函式在派生類中重新定義以後,派生類才能例項化出物件。
用**來直觀說明一下吧
class base
;class derived :public base
{};在這段**中,base就是乙個抽象類,而test函式就是乙個純虛函式
所以,不能使用base類 來定義乙個物件 。
那些函式可以定義為虛函式呢?????
總結一句話就是 只有類的非靜態成員函式才能定義為虛函式
但是類的建構函式不能定義為虛函式,因為建構函式是在類物件建立時呼叫的,
而虛函式是通過基類的指標和派生類的指標和引用呼叫的,
如果將建構函式定義為虛函式,無法正常實現虛函式與建構函式的功能。
一般情況下,要將基類析構函式定義為虛函式,為什麼呢???
class base
;class derived :public base
;當宣告乙個基類的引用 ,用派生類賦值int mian()
當函式結束後 ,rb類析構時,應該呼叫的派生類的析構函式,所以應該將基類的析構函式定義為虛函式,
來根據引數的不同呼叫不同的析構函式;
至於為什麼只有非靜態的成員函式才能定義 成虛函式??
我還沒搞清楚》之後再研究研究
下面是對上面所說的虛函式編寫時所要注意的地方(對上面的總結)
1、派生類重寫基類的虛函式實現多型,要求函式名、引數列表、返回值完全相同。(協變除外)
2、基類中定義了虛函式,在派生類中該函式始終保持虛函式的特性。(就像是上面說的函式test2)
3、關於哪些函式可以定義為虛函式,只有類的非靜態成員函式才能定義為虛函式,靜態成員函式不能定義為虛函式。(建構函式除外 )
4、建構函式不能定義為虛函式,雖然可以將operator=定義為虛函式,但最好不要這麼做,使用時容
易混淆5、如果在類外定義虛函式,只能在宣告函式時加virtual關鍵字,定義時不用加(宣告和定義只在乙個地方加上virtual)
6、不要在建構函式和析構函式中呼叫虛函式,在建構函式和析構函式中,物件是不完整的,可能會
出現未定義的行為。(因為虛函式是通過虛表來呼叫的,構造與析構時,物件不完整)。
7、最好將基類的析構函式宣告為虛函式。(析構函式比較特殊,因為派生類的析構函式跟基類的析構
函式名稱不一樣,但是構成覆蓋,這裡編譯器做了特殊處理)
C 多型解析
今天我們,來將將c 的三大特性之一的 多型性 為什麼會有這個呢?因為,我們編寫 時,有的時候,當物件不同時,就需要呼叫不同的函式。在這個時候就需要使用的多型了。再說類的多型性之前我先來說說物件這個概念。物件的概念可以分為兩種型別 所謂的靜態型別,就是一般的型別 而動態型別,舉個例子來說就像是賦值相容...
C 多型繼承解析
在c 中,類的概念是最重要的,類就是實物的乙個模版,或是一種抽象的方法和資料的封裝,每用類宣告乙個變數,那我們就叫做類的例項化,在類的生存區域,會呼叫建構函式,在臨界區則會呼叫析構函式,構造的物件在記憶體中的表示就是類中的資料成員依次構造,如class string 在記憶體中這個string類共有...
C 基礎解析之 多型
今天繼續和大家一起 c 我們今天來聊聊c 中物件導向中乙個重要的特性 多型 簡單的一句話解釋多型 相同的方法呼叫可以實現不同的實現方式。通俗的說多型就是不同的表現形式,比如 中國人吃飯用筷子,歐洲以及北美都用刀叉,還有一些另類的人種直接上手,雖然他們的行為方式不同,但是他們有乙個目的就是吃飯!說白了...