簡體   English   中英

從 C++ 中的 class 析構函數調用虛擬 function

[英]Calling virtual function from a class destructor in C++

在構造函數或析構函數中調用虛函數的問題已經在許多其他問題和資源中討論過,但我想澄清一些關於它的東西,我仍然感到缺失。

例如,在 Scott Meyers, Effective C++, Item 9 中有完整的解釋。 但最后的評論是

在構造或銷毀期間不要調用虛函數,因為這樣的調用永遠不會 go 到比當前執行的構造函數或析構函數更派生的 class

所以我想了解在什么意義上從構造函數或析構函數調用虛擬 function 是不安全的。

  • 因為虛擬表狀態在析構函數中是“不確定的”,所以我可能會得到意外的運行時行為,這是否不安全?
  • 或者,從某種意義上說它是不安全的,因為我可能會得到與我預期不同的行為,所以它是不可維護的?

謝謝

因為虛擬表狀態在析構函數中是“不確定的”,所以我可能會得到意外的運行時行為,這是否不安全?

C++ 標准沒有討論 vtable 實現。 它討論了行為。 並且行為是調用被靜態解析(好像)。

就實現而言,那些通常“恢復” vptr 使其指向當前被破壞的類的 vtable,在析構函數執行的早期。

或者,從某種意義上說它是不安全的,因為我可能會得到與我預期不同的行為,所以它是不可維護的?

取決於你的期望。 如果您知道呼叫是如何解決的,您將得到您所期望的

class Thing {
public:
    virtual ~Thing() { frombulate(); }
    void frombulate() const { do_frombulation(); }
private:
    virtual void do_frombulation() const = 0;
};

inline void Thing::do_frombulation() const {}

就像我說的,你可能知道會發生什么行為,所以即使do_frombulation是純虛擬的,你也提供了一個實現。

如果不知道,您可能已經省略了空定義。 在這種情況下,您的程序將表現出未定義的行為(可能會崩潰,因為Thing的 vtable 中的該條目不會由有效地址填充)並且您可能會對此感到驚訝。 如果您直接在構造函數/析構函數體中調用未實現的純虛擬do_frombulation ,編譯器可能會通知您,但它無法檢查所有執行路徑。

從某種意義上說,我可能會得到意外的運行時行為,這是否不安全......

意外行為正是它不安全的意義。 該程序的讀者或作者可能會期望調用虛擬 function 會調用最派生的覆蓋。 這個假設在 detructor(也不是在構造函數)中是不正確的,這可能是出乎意料的。

...因為虛擬表狀態在析構函數中是“不確定的”?

這種行為沒有任何“不確定性”。

或者,從某種意義上說它是不安全的,因為我可能會得到與我預期不同的行為,所以它是不可維護的?

意外行為通常不同於人們預期的行為。 所以,是的。

暫無
暫無

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

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