【C++面試】關於虛函數的常見問題


1.虛函數的代價

1)帶有虛函數的每個類會產生一個虛函數表,用來存儲虛成員函數的指針

2)帶有虛函數的每個類都會有一個指向虛函數表的指針

3)不再是內斂函數,因為內斂函數可以在編譯階段進行替代,而虛函數表示等待,在運行階段才能確定到達采用哪種函數,所以虛函數不是內斂函數

 

2.那些函數不能是虛函數?

1)構造函數:對象的虛函數表指針需要通過構造函數初始化

2)內聯函數:內聯函數可以在編譯階段進行函數體的替換,而虛函數需要在運行期間進行確定

3)靜態函數:靜態函數不屬於對象而屬於類,因為靜態成員函數沒有this指針,所以無法訪問對象的虛表指針,也就

無法訪問類的虛函數表,將靜態函數設置成虛函數也就沒有任何意義,所以c++語法不支持將靜態函數設置成虛函數

4)友元函數:友元函數不屬於類,也不能被繼承,沒有繼承特性的函數沒有虛函數的說法

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;
}
View Code

 

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;
}
View Code

 

5.虛析構函數的作用?父類的析構函數為什么一定要設置成虛函數?

父類虛析構函數就是為了避免內存泄漏,防止子類內存得不到釋放造成內存泄漏

1.當父類的析構函數不聲明成虛析構函數時,當子類繼承父類,父類指針指向子類對象,delete掉父類指針,只會調動父類的析構函數,而不會調用子類的析構函數,從而造成子類對象內存泄漏

2.當父類的析構函數聲明成虛析構函數時,當子類繼承父類,父類指針指向子類對象,delete掉父類指針,先調動父類的析構函數,然后調用子類的析構函數,不存在子類對象內存泄漏的問題

只要存在繼承關系,則父類的虛函數必須定義成虛函數!

 

6.構造函數和析構函數中為什么不可以調用虛函數?

背景知識:

1.構造子類對象時,首先調用父類構造函數初始化對象的父類部分,在執行父類的構造函數時,對象的子類部分都是未初始化的,實際上此時對象還不是一個子類對象

2.析構子類對象時,先析構子類部分,然后按照構造順序逆序析構父類部分

所以在運行子類的構造和析構函數時,對象都是不完整的,為了適應這種不完整,編譯器視對象類型為當前構造或析構函數所在類的類型,由此造成的結構就是:在父類的構造或析構函數中,會將子類對象當作父類對象看待

在這樣的背景下

如果我們在父類的構造或析構函數中調用虛函數,調用的往往是當前類的虛函數,達不到多態的效果,跟普通函數調用沒有區別

 

7.構造函數為什么不能為虛函數?什么情況下析構函數必須為虛函數?

1)因為虛函數表指針必須在構造函數中初始化,所以構造函數不能為虛函數!

2)當存在繼承關系時,父類的析構函數必須為虛函數,這樣在父類指針指向子類對象,delete父類指針時,子類對象才不會內存泄漏

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM