1.虛函數的代價ios
1)帶有虛函數的每一個類會產生一個虛函數表,用來存儲虛成員函數的指針c++
2)帶有虛函數的每一個類都會有一個指向虛函數表的指針ide
3)再也不是內斂函數,由於內斂函數能夠在編譯階段進行替代,而虛函數表示等待,在運行階段才能肯定到達採用哪一種函數,因此虛函數不是內斂函數函數
2.那些函數不能是虛函數?this
1)構造函數:對象的虛函數表指針須要經過構造函數初始化spa
2)內聯函數:內聯函數能夠在編譯階段進行函數體的替換,而虛函數須要在運行期間進行肯定指針
3)靜態函數:靜態函數不屬於對象而屬於類,由於靜態成員函數沒有this指針,因此沒法訪問對象的虛表指針,也就code
沒法訪問類的虛函數表,將靜態函數設置成虛函數也就沒有任何意義,因此c++語法不支持將靜態函數設置成虛函數對象
4)友元函數:友元函數不屬於類,也不能被繼承,沒有繼承特性的函數沒有虛函數的說法blog
5)類外的普通函數:類外普通函數不是類的成員函數,一樣不具有繼承特性,也就沒有虛函數的說法
3.虛函數和純虛函數的區別?
1)純虛函數只有定義,沒有實現,虛函數既有定義,又有實現
2)含有純虛函數的類不能定義對象,含有虛函數的類能夠定義對象
4.菱形繼承的內存結構?如何解決菱形繼承存在的問題?


#include <iostream> using namespace std; class A { public: int x; virtual int getx() { return x; } }; class B:public A{}; class C:public A{}; class D:public B,public C{}; int main() { D d; //如下代碼不會被任何編譯器經過,由於存在菱形繼承問題 cout<<d.getx()<<endl; }
1)菱形繼承的內存結構:如今有A,B,C,D四個類,B,C分別繼承A類,D經過多重繼承繼承了BC兩個類,如今D類中有兩個getx(),D類不知道調用哪個getx()
2)菱形繼承的解決辦法:虛繼承
BC類都用Virtual標註,保證只有一個getx()被建立


#include <iostream> using namespace std; class A { public: int x=5; virtual int getx() { return x; } }; class B:virtual public A{}; class C:virtual public A{}; class D:public B,public C{}; int main() { D d; cout<<d.getx()<<endl; }
5.虛析構函數的做用?父類的析構函數爲何必定要設置成虛函數?
父類虛析構函數就是爲了避免內存泄漏,防止子類內存得不到釋放形成內存泄漏
1.當父類的析構函數不聲明成虛析構函數時,當子類繼承父類,父類指針指向子類對象,delete掉父類指針,只會調動父類的析構函數,而不會調用子類的析構函數,從而形成子類對象內存泄漏
2.當父類的析構函數聲明成虛析構函數時,當子類繼承父類,父類指針指向子類對象,delete掉父類指針,先調動父類的析構函數,而後調用子類的析構函數,不存在子類對象內存泄漏的問題
只要存在繼承關係,則父類的虛函數必須定義成虛函數!
6.構造函數和析構函數中爲何不能夠調用虛函數?
背景知識:
1.構造子類對象時,首先調用父類構造函數初始化對象的父類部分,在執行父類的構造函數時,對象的子類部分都是未初始化的,實際上此時對象還不是一個子類對象
2.析構子類對象時,先析構子類部分,而後按照構造順序逆序析構父類部分
因此在運行子類的構造和析構函數時,對象都是不完整的,爲了適應這種不完整,編譯器視對象類型爲當前構造或析構函數所在類的類型,由此形成的結構就是:在父類的構造或析構函數中,會將子類對象看成父類對象看待
在這樣的背景下
若是咱們在父類的構造或析構函數中調用虛函數,調用的每每是當前類的虛函數,達不到多態的效果,跟普通函數調用沒有區別
7.構造函數爲何不能爲虛函數?什麼狀況下析構函數必須爲虛函數?
1)由於虛函數表指針必須在構造函數中初始化,因此構造函數不能爲虛函數!
2)當存在繼承關係時,父類的析構函數必須爲虛函數,這樣在父類指針指向子類對象,delete父類指針時,子類對象纔不會內存泄漏