2017-02-22 30 views
0

只是出於好奇,我試圖做下面的例子,看看編譯器是否給我一個警告,所以不要調用一個以堆棧溢出結束的無限循環。我想也許有一種不同於只調用普通函數或方法的行爲。但事實並非如此。有沒有特別的解釋呢,還是隻是作爲正常的函數調用來處理,因爲我通過使用this運算符顯式調用基類析構函數?編譯器如何處理派生析構函數中的基類析構函數調用?

例子:

class A { 
    virtual ~A(); 
}; 

class B : A { 
    virtual ~B() { this->~A(); } 
}; 
+2

'virtual void〜A();' - 這不應該編譯,析構函數不返回任何東西,並且普通的方法名稱不能包含tilda。 – yeputons

+0

@yeputons right,sry,is typo –

+4

它會通過調用'〜A()'兩次導致未定義的行爲(因爲有一個隱含的調用,一旦'〜B()'的主體退出) –

回答

2

@ M.M的評論擊中它。你正在調用析構函數兩次。這是未定義的行爲,可能會發生任何事情,包括您觀察到的行爲。

(在現實中,這些析構函數調用的最有可能的一個修改對象的vptr的,這意味着隨後的析構函數調用不再去最派生的對象。但是,這只是一個猜測。)

正確的事要做的是不要手動調用析構函數。

+1

C++ 14 [class.dtor]/15是具體說第二個析構函數調用的子句是UB,對於具有非平凡析構函數的類(這是因爲'virtual'使它不平凡) –

0

調用派生類虛擬析構函數會導致調用基類析構函數。但不反之亦然。

1

派生類中的虛擬析構函數將總是首先調用父類析構函數,按遞歸順序調用最「祖先」基類的析構函數,然後調用第二個「祖先」等等。想象一下,Child從繼承自GrandParent的Parent繼承。 Child類的析構函數實際上會調用GrandParent的析構函數,然後調用Parent的析構函數,然後調用Child的析構函數。

事實上,您的派生類構造函數也會以相同的遞歸順序調用它們的父類構造函數。你必須想象派生類,比如「圖層蛋糕」:每個繼承實例都會爲你的對象添加一個圖層。所以Child類有3層{GrandParent,Parent,Child},每層的構造/銷燬都由相應的類來處理。

你試圖嘗試調用父析構函數兩次,這是一個壞主意。一般情況下,您不必顯式調用析構函數,除非您超載了new運算符。看到這個答案的更多細節:Is calling destructor manually always a sign of bad design?

相關問題