virtual
Virtual是C++ OO機制中很重要的一個關鍵字。只要是學過C++的人都知道在類Base中加了Virtual關鍵字的函數就是虛擬函數(例如函數print),于是在Base的派生類Derived中就可以通過重寫虛擬函數來實現對基類虛擬函數的覆蓋。當基類Base的指針point指向派生類Derived的對象時,對point的print函數的調用實際上是調用了Derived的print函數而不是Base的print函數。這是面向對象中的多態性的體現。(關于虛擬機制是如何實現的,參見Inside the C++ Object Model ,Addison Wesley 1996)
class Base { public:Base(){} public:virtual void print(){cout<<"Base";} };class Derived:public Base { public:Derived(){} public:void print(){cout<<"Derived";} };int main() {Base *point=new Derived();point->print(); }Output: Derived這也許會使人聯想到函數的重載,但稍加對比就會發現兩者是完全不同的:
(1)?????? 重載的幾個函數必須在同一個類中;
覆蓋的函數必須在有繼承關系的不同的類中
(2)?????? 覆蓋的幾個函數必須函數名、參數、返回值都相同;
重載的函數必須函數名相同,參數不同。參數不同的目的就是為了在函數調用的時候編譯器能夠通過參數來判斷程序是在調用的哪個函數。這也就很自然地解釋了為什么函數不能通過返回值不同來重載,因為程序在調用函數時很有可能不關心返回值,編譯器就無法從代碼中看出程序在調用的是哪個函數了。
(3)?????? 覆蓋的函數前必須加關鍵字Virtual;
重載和Virtual沒有任何瓜葛,加不加都不影響重載的運作。
?
關于C++的隱藏規則:
我曾經聽說過C++的隱藏規則:
(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual
關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數與基類的函數同名,并且參數也相同,但是基類函數沒有virtual
關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)。
bp 和dp 指向同一地址,按理說運行結果應該是相同的,而事實上運行結果不同,所以他把原因歸結為C++的隱藏規則,其實這一觀點是錯的。決定bp和dp調用函數運行結果的不是他們指向的地址,而是他們的指針類型。“只有在通過基類指針或引用間接指向派生類子類型時多態性才會起作用”(C++ Primer 3rd Edition)。pb是基類指針,pd是派生類指針,pd的所有函數調用都只是調用自己的函數,和多態性無關,所以pd的所有函數調用的結果都輸出Derived::是完全正常的;pb的函數調用如果有virtual則根據多態性調用派生類的,如果沒有virtual則是正常的靜態函數調用,還是調用基類的,所以有virtual的f函數調用輸出Derived::,其它兩個沒有virtual則還是輸出Base::很正常啊,nothing surprise!?
所以并沒有所謂的隱藏規則,雖然《高質量C++/C 編程指南》是本很不錯的書,可大家不要迷信哦。記住“只有在通過基類指針或引用間接指向派生類子類型時多態性才會起作用”。
轉載于:https://www.cnblogs.com/yuandonghua/p/10531753.html
總結
- 上一篇: VCL界面控件DevExpress VC
- 下一篇: [转帖]面包屑设计