1. 程式人生 > >C++建構函式和解構函式--從常見的面試題說起系列1

C++建構函式和解構函式--從常見的面試題說起系列1

class A

{

public:

    A(){a=0}

    virtual ~A(){printf "aaa";}}

private:

    int a;

}

class B: public A

{

public:

    B(){a=2}

    virtual ~B(){printf "bbb";}

}

常常有這樣兩個面試題目:

1)

A* p = new B;

delete p;

p->a 等於多少?

2)

解構函式的列印順序.

類A 和 類B的解構函式為什麼要定義為虛擬函式,如果不定義為虛擬函式會有什麼問題或隱患?

其實這兩道題目就是考的C++中類的建構函式和解構函式的呼叫順序問題,其中第一套題比較簡單,大部分面試者都能正確回答,第二道題回答完整的就比較少了,第二題還考到了多型(虛擬函式)的知識點,多型在後續的文章單獨闡述。

建構函式:

對於有整合關係的建構函式,定義子類的物件時,會先呼叫父類的建構函式,再呼叫子類的解構函式。

因此第一套題先回呼叫A的建構函式,此時b.a為0,然後呼叫B的建構函式,最終b.a的值為2.

解構函式:

對於解構函式,大部分面試者回答的比較簡單,回答的不夠全面。

刪除物件時,呼叫的第一個解構函式,由解構函式是否是虛擬函式確定:

1)如果是虛擬函式,則會呼叫指標指向的實際物件的類的解構函式,但是解構函式不僅僅是虛擬函式,它還會自動往上呼叫基類的解構函式。

2)如果不是虛擬函式,則由刪除指標定義的型別來確定。

這道題中,delete p時,由於是解構函式,則會先呼叫B的解構函式,再呼叫A的解構函式

如果不是虛擬函式,則只會呼叫A的解構函式。但是如果是 B* p = new B的話,即使不是虛擬函式,也一樣會先呼叫B的解構函式,再呼叫A的解構函式。

類成員申請的資源通常都是在解構函式中釋放,由於解構函式的這個特點,因此解構函式通常定義為虛擬函式,因為如果不是虛擬函式的話,很有可能不會呼叫到子類的解構函式,導致子類申請的資源沒有被釋放。