直接看這段代碼
- class CBase
- {
- public:
- virtual int func(int num=1) const //虛函數
- {
- cout<<"CBase function! "<<num<<endl;
- return 0;
- }
- int fun2()
- {
- cout<<"CBase function2! "<<endl;
- return 0;
- }
- };
- class CDerive : public CBase
- {
- public:
- int func(int num=2) const //在派生類中重新定義虛函數
- {
- cout<<"CDerive function! "<<num<<endl;
- return 0;
- }
- int fun2()
- {
- cout<<"CDerive function2! "<<endl;
- return 0;
- }
- };
- int main()
- {
- CDerive* obj1=new CDerive;
- CBase* p1=obj1;
- p1->func();
- obj1->func();
- p1->fun2();
- obj1->fun2();
- delete obj1;
- return 0;
- }
代碼執行的結果爲:
CDerive function! 1
CDerive function! 2
CBase function2!
CDerive function2!
Press any key to continue
都明白了不?
不明白先看點背景知識。
靜態多態性:函數多態性——函數重載
模板多態性——C++模板(類模板、函數模板)
動態多態性:虛函數(只有用地址才能實現動態多態性)
只有採用“指針->函數()”或“引用變量.函數()”的方式調用C++類中的虛函數纔會執行動態綁定。對於C++中的非虛函數,因爲其不具備動態綁定的特徵,所以不管採用什麼樣的方式調用,都不會執行動態綁定。
C++語言成員函數的調用和綁定方式總結
代碼形式 對於虛函數 對於非虛函數
作用 綁定方式 作用 綁定方式
類名::函數() 調用指定類的指定函數 靜態綁定 調用指定類的指定函數 靜態綁定
對象名.函數() 調用指定對象的指定函數 靜態綁定 調用指定對象的指定函數 靜態綁定
引用變量.函數() 調用被引用對象所屬類的指定函數 動態綁定 調用引用變量所屬類的指定函數 靜態綁定
指針->函數() 調用被引用對象所屬類的指定函數 動態綁定 調用指針變量所屬類的指定函數 靜態綁定
注:被引用對象所屬類 是 指針 或 引用 指向的對象的實際類型;
引用變量所屬類、指針變量所屬類 是 定義 引用變量、指針變量的類型;
以上兩種類型可能相同,也可能不同。
從上表可以看出,執行動態綁定的只有通過地址,即只有通過指針或引用變量才能實現,而且還必須是虛函數。從概念上來說,虛函數機制只有在應用於地址時纔有效,因爲地址在編譯階段提供的類型信息不完全。
先看第一條:
CDerive function! 1
由p1->func();調用的虛函數,雖然p1爲基類指針,但是調用到的函數卻應該是被引用對象所屬類的指定函數,也就是子類的虛函數。
CDerive* obj1=new CDerive;已經決定了p1能調用到的是子類虛函數,這就是動態綁定。
但是再看看後面的參數1,子類虛函數int func(int num=2) const 參數應該是2,這個我還不能很好的解釋。(*-*,跟飛雪溝通溝通再補充。。)
因爲,參數是在編譯時綁定,所以p1->func();的缺省參數還是基類函數的參數,沒有跟上動態綁定。只能這樣說了,反正飛雪說多了,我也搞不清。
第2條:
CDerive function! 2
這是我們需要的結果,不用解釋了吧
第3條:
CBase function2!
靜態綁定,根據指針類型調用。
第4條同3