常見筆 面試題 之建構函式和析構函式

2021-07-23 03:51:58 字數 2780 閱讀 8960

建構函式是用來初始化乙個物件的,而析構函式的作用則是釋放物件占用的空間。如果將虛函式、建構函式和析構函式結合起來會有怎麼樣的效果呢?

建構函式可以是虛函式嗎?

答:建構函式不可以是虛函式!基於以下幾點原因:

(1)構造乙個物件的時候,必須知道物件的實際型別,而虛函式行為是在執行期間動態確定實際型別的。在構建乙個物件時,建構函式執行期間,物件未完全構建完成,編譯器無法知道物件的實際型別,如果建構函式為虛函式,虛函式的執行是基於物件型別確定的,然而構建的物件本身自己都無法確定自己的型別,虛函式更加無法正確執行!

(2)虛函式的執行依賴於虛函式表。而虛函式表的初始化工作是在建構函式中完成的,即在建構函式中初始化vptr,讓他指向正確的虛函式表。而在構造物件期間,虛函式表還未被初始化,將導致虛函式無法工作。

(3)虛函式的意思就是開啟動態繫結,程式會根據物件的動態型別來選擇要呼叫的方法。然而在建構函式執行的時候,這個物件的動態型別還不完整,沒有辦法確定它到底是什麼型別,故建構函式不能動態繫結。(動態繫結是根據物件的動態型別而不是函式名,在呼叫建構函式之前,這個物件根本就不存在,它怎麼動態繫結?)

析構函式可以是純虛函式嗎?能舉個例子嗎?

答:析構函式可以是純虛函式!如果乙個類要作為基類存在,最好將該類的析構函式申明虛函式(除非不使用基類指標的方式構造子類)。

(1)擁有純虛函式的類稱為抽象類,專門提供函式介面,不能例項化。如果某個類需要作為乙個抽象類,但是其中並沒有其他方法,這時可以將析構函式宣告為純虛函式。(因為建構函式不能是虛函式,更不必提純虛函式了)

(2)例子:

注意test基類中的析構函式是純虛函式,但是該析構函式還是有實現,而且必須要有實現!!!test::~test(){}這個定義是必需的,因為虛析構函式工作的方式是:最底層的派生類的析構函式最先被呼叫,然後各個基類的析構函式被呼叫。這就是說,即使是抽象類,編譯器也要產生對~test的呼叫,所以要保證為它提供函式體。如果不這麼做,鏈結器就會檢測出來(報錯error link 1120),最後還是得回去把它添上。雖然抽象類的析構函式可以是純虛函式,但要例項化其派生類物件,仍必須提供抽象基類中析構函式的函式體。

**通常情況下,抽象類的純虛函式實現必須且只能由派生類實現,但是對於基類的純虛析構函式實現可以由自身給出,也可以由派生類給出。

擁有純虛析構函式的類也是抽象類!!!**

下面**執行後會發生記憶體洩漏嗎?如果存在該如何修改?

#include 

using

namespace

std;

//基類

class base

~base()

void dosomething()

};//派生類

class derived : public base

~derived()

void dosomething()

};int main()

答:此段**執行後將會發生記憶體洩漏,由於基類指標指向的是子類物件,但是由於基類的析構函式不是虛函式,基類指標無法找到他所指向的實際型別,從而在delete的時候只能釋放derived物件中從基類繼承的部分,其餘部分將無法得到釋放導致記憶體洩漏!

修改:

#include 

using

namespace

std;

//情景1:普通成員函式和析構函式,都不是虛函式

class base

//父類的析構函式,是虛函式,只做了這裡的更改

virtual ~base()

//普通成員

void dosomething()

};//派生類

由此可以看出,這個時候,就真正實現了將實際型別物件進行釋放的。同時可以得到,如果父類析構是虛函式,子類呼叫析構函式的話,會先呼叫子類的析構函式,之後會呼叫父類的析構函式

其實這裡父類的析構函式加上了virtual,並不是說pbase釋放的時候,同時呼叫了子類的析構函式和父類的析構函式,它實際上指向的是子類的虛函式表,那麼就是說父類指標最終只呼叫了子類的析構函式,由c++類本身特性,當子類析構函式呼叫的時候,會自動呼叫父類的析構函式,完成了釋放。

相關小結

對於base *pbase = new derived;

如果父類函式不是析構函式,那麼pbase只能「看見」父類本身的函式,這是因為沒有虛函式表讓它可以找到本身

如果父類析構函式是虛函式,如果delete pbase,將會先呼叫子類函式的析構函式,然後子類析構函式自動呼叫父類的析構函式,真正實現了資源釋放,防止了記憶體洩露構造派生類的時候,會先構造基類部分,然後構造子類部分;撤銷派生類物件的時候,會先撤銷派生類部分,然後撤銷基類部分

建構函式與析構函式區別之面試題目

一 建構函式 建構函式是特殊的成員函式。建構函式的特殊之處 1 建立類型別的新物件,系統會自動呼叫建構函式 2 建構函式是為了保證物件的每個資料成員都被初始化 建構函式的特點 a 函式名和類名完全相同 b 不能定義建構函式的型別 返回型別 也不能使用void c 通常情況下建構函式應宣告為共有函式,...

C 之建構函式和析構函式

我們已經知道了物件就是類的例項,二者的關係就相當於資料型別與它的變數的關係。每個物件區別於其他物件的地方就是依靠它的自身屬性,即資料成員的值。c 中,物件在定義的時候進行的資料成員的設定,稱為物件的初始化。同樣,在特定物件使用結束時,還要對資料成員進行一些清理工作。c 中對類的初始化和清理的工作,分...

C 之建構函式和析構函式

一 建構函式 1 物件的初始化和建構函式 類是一種抽象的資料型別,它不占用儲存空間,不能容納具體的資料。因此在類宣告中不能給資料成員賦初值。例如 錯誤 class complex 與使用變數一樣,使用物件時也應該先定義,後使用。在定義物件時,對資料成員賦初值,稱為初始化。例如 class compl...