您好,登錄后才能下訂單哦!
本篇內容介紹了“C++虛函數怎么使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
首先來看下面這一段代碼,首先創建兩個類,一個是Dog,另一個是Cat,他們有一個共同的屬性:Run。在定義中每個動物都需要創建一個類,比較繁瑣,所以在下面的例子中,我們可以把他們簡化。
#include <iostream> using namespace std; class Dog{ public: void Run(){ cout<<"Dog->Run"<<endl; } }; class Cat{ public: void Run(){ cout<<"Cat->Run"<<endl; } }; int main() { Dog d; d.Run(); Cat c; c.Run(); return 0; }
這里使用多態和虛函數,而Animal提供統一的接口,供子類使用,雖然代碼繁瑣,但提高了整個工程的可擴展性和靈活性。
在普通函數前加上關鍵字 virtual 構成虛函數,子類需要重寫父類的虛函數,這樣在調用的時候,會覆蓋掉父類的虛函數 Run,去執行子類的Run。
#include <iostream> using namespace std; class Animal{ public: virtual void Run(){ cout<<"Animal->Run"<<endl; } }; class Dog :public Animal{ public: void Run(){ cout<<"Dog->Run"<<endl; } }; class Cat:public Animal{ public: void Run(){ cout<<"Cat->Run"<<endl; } }; int main() { Animal *ani; ani = new Dog; ani->Run(); delete ani; ani = new Cat; ani->Run(); delete ani; return 0; }
結果如下:
所以在這里只需要修改ani的指向就可以實現不同方法。如果不存在虛函數,把Animal類的關鍵詞virtual去掉會怎么樣呢,顯然,他們會默認實現父類Run的方法。
class Animal{ public: void Run(){ cout<<"Animal->Run"<<endl; } };
所以引入虛函數是為了實現動態多態,指向不同的子類來實現不同的方法。
因為父類的函數可以不做任何操作,所以這里可以直接等于0;實現純虛函數。
//虛函數 class Animal{ public: virtual void Run(){ cout<<"Animal->Run"<<endl; } };
//純虛函數 class Animal{ public: virtual void Run()=0; };
虛函數與純虛函數的區別:
純虛函數只是一個接口,只能供子類去重寫實現方法。而虛函數在里面也可以去實現父類的功能。只需要指向父類的方法即可。
總結:虛函數在子類里面也可以不進行重寫,但純虛函數必須在子類去實現,如果把子類中的Run方法去掉,只留下父類中的純虛函數,那么編譯器會報錯,這里大家可以試試。
Animal內部的結構是什么樣呢?這里有一個虛函數指針(vfptr)和虛函數表(vftable)。 指針(vfptr)指向虛函數表,在虛函數表(vftable)內記錄著虛函數的地址,即Run函數的地址。
當子類的Dog去繼承父類后,父類的虛函數表相應的也繼承下來,子類也會保存一份和父類相同的。
注意!這時候如果發生重寫,即子類重寫了父類的虛函數,則子類的虛函數表會覆蓋父類繼承下來的虛函數表。但父類的虛函數表不會發生改變。
當父類的指針或者引用指向子類的對象時,就發生了多態。
下面的代碼中是指向了Dog,所以會去Dog的虛函數表中找到相應的函數,在運行階段發生了動態多態。
Animal *ani; ani = new Dog; ani->Run();
“C++虛函數怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。