c 有關建構函式和析構函式中呼叫虛函式問題

2022-04-04 06:52:52 字數 1599 閱讀 6497

今天看了一道迅雷的筆試題目,然後引起一段思考,題目如下:

下列關於虛函式的說法正確的是()

a、在建構函式中呼叫類自己的虛函式,虛函式的動態繫結機制還會生效。

b、在析構函式中呼叫類自己的虛函式,虛函式的動態繫結機制還會生效。

c、靜態函式不可以是虛函式

d、虛函式可以宣告為inline

此題答案給的是bcd,當時我就產生很大疑惑,所以我對四個選項依依來驗證。

1、首先對於ab選項,我做了如下**:

1 #include 2

using

namespace

std;

3class

classa412

virtual ~classa()

1318

void

virtual

output()

1922

};23

24class classb:public

classa

2533

virtual ~classb()

3439

void

output()

4043

44};

4546

47int

main()

48

在vs2010中輸出結果為:

可以看到,在new classb時,雖然在父類classa的建構函式調了的是被classb覆蓋的虛函式output(),但是實際上還是呼叫的classa的output。這是因為

繼承類在構造的時候總是首先呼叫其基類的建構函式來對屬於其基類的部分進行構造,在這個時候,整個類被當作基類來處理,繼承類的部分對整個類來說好像不存在一樣,直到基類的建構函式退出並進入繼承類的建構函式,該類才被當作繼承類來出來處理。對析構也一樣,只是析構的順序正好相反。

由此可知ab錯誤。(可以參考:

對於c選項:

因為靜態成員函式沒有this,也就沒有存放vptr的地方,同時其函式的指標存放也不同於一般的成員函式,其無法成為乙個物件的虛函式的指標以實現由此帶來的動態機制。靜態是編譯時期就必須確定的,虛函式是執行時期確定的。故c項正確。

對於d選項:

inline函式和virtual函式有著本質的區別,inline函式是在程式被編譯時就展開,在函式呼叫處用整個函式體去替換,而virtual函式是在執行期才能夠確定如何去呼叫的,因而inline函式體現的是一種編譯期機制,virtual函式體現的是一種執行期機制。

因此,內聯函式是個靜態行為,而虛函式是個動態行為,他們之間是有矛盾的。

函式的inline屬性是在編譯時確定的, 然而,virtual的性質則是在執行時確定的,這兩個不能同時存在,只能有乙個選擇,檔案中宣告inline關鍵字只是對編譯器的建議,編譯器是否採納是編譯器的事情。

我並不否認虛函式也同樣可以用inline來修飾,但你必須使用物件來呼叫,因為物件是沒有所謂多型的,多型只面向行為或者方法,但是c++編譯器,無法保證乙個內聯的虛函式只會被物件呼叫,所以一般來說,編譯器將會忽略掉所有的虛函式的內聯屬性。

所以d正確。

故此題答案為cd

有關析構函式呼叫

如果在乙個函式中定義了乙個物件 它是自動區域性物件 當這個函式被呼叫結束時,物件應該釋放,在物件釋放前自動執行析構函式。static區域性物件在函式呼叫結束時物件並不釋放,因此也不呼叫析構函式,只在main函式結束或呼叫exit函式結束程式時,才呼叫static區域性物件的析構函式。如果定義了乙個全...

C 顯示呼叫建構函式和析構函式

建構函式和析構函式可不可以顯示呼叫 class a a void main 此時的輸出結果是 a constructor a constructor 顯示呼叫建構函式的結果。a destrucotr 顯示呼叫析構函式的結果,此時物件並沒有銷毀。a destructor 物件銷毀時自動呼叫析構函式。總...

C 顯示呼叫建構函式和析構函式

類在new的時候其實做了兩件事情 1 呼叫malloc分配所需的記憶體 實際上是呼叫operator new 2 呼叫建構函式 類在delete的時候其實也做了兩件事 1 呼叫析構函式 2 呼叫free釋放記憶體 實際上是呼叫operator delete 直接通過 類名 建構函式或析構函式clas...