簡體   English   中英

編譯器如何處理派生析構函數中的基類析構函數調用?

[英]How does the compiler handle base class destructor calls in the derived destructor?

出於好奇,我嘗試執行以下示例,以查看編譯器是否向我發出警告,而不是調用導致堆棧溢出的無限循環。 我認為也許有不同的行為,而不僅僅是調用正常的函數或方法。 但是事實並非如此。 有什么特別的解釋嗎?或者因為我使用this運算符顯式地調用了基類的析構函數,所以它只是作為普通的函數調用處理嗎?

例:

class A {
  virtual ~A();
};

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

@MM的評論擊中了它。 您要兩次調用析構函數。 這是未定義的行為,任何事情都可能發生,包括您觀察到的行為。

(實際上,這些析構函數調用中很可能會修改對象的vptr,這意味着后續的析構函數調用將不再轉到最派生的對象。但這只是一個猜測。)

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

派生類中的虛擬析構函數將始終首先以遞歸順序調用父類析構函數,這樣將調用最“祖先”的基類析構函數,然后調用第二最“祖先”的析構函數,以此類推。子級從父級繼承,父級從GrandParent繼承。 Child類的析構函數實際上將調用GrandParent的析構函數,然后是Parent的析構函數,然后是Child的析構函數。

實際上,您的派生類構造函數還以相同的遞歸順序調用其父類構造函數。 您必須想象派生類就像一個“蛋糕”:每個繼承實例都為您的對象添加了一層。 因此,Child類具有3層{GrandParent,Parent,Child},每層的構造/破壞都由相應的類處理。

您嘗試執行的操作將嘗試兩次調用父析構函數,這是個壞主意。 通常,除非您重載了new運算符,否則不必顯式調用析構函數。 請參閱此答案以獲取更多詳細信息: 手動調用析構函數是否總是表明設計不好?

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM