
C.35: A base class destructor should be either public and virtual, or protected and nonvirtual
基類的析構函數要么是公開的虛函數,要么是保護的非虛函數
Reason(原因)
To prevent undefined behavior. If the destructor is public, then calling code can attempt to destroy a derived class object through a base class pointer, and the result is undefined if the base class's destructor is non-virtual. If the destructor is protected, then calling code cannot destroy through a base class pointer and the destructor does not need to be virtual; it does need to be protected, not private, so that derived destructors can invoke it. In general, the writer of a base class does not know the appropriate action to be done upon destruction.
為了避免無定義的行為。如果析構函數是公有的,那么調用側的代碼就會嘗試使用基類指針銷毀派生類的對象,在基類的析構函數為非虛函數時其結果時沒有定義的。如果析構函數時保護的,那么調用側代碼就無法通過基類類型指針銷毀派生類對象,這是析構函數就沒有必要一定是虛函數。析構函數是保護而不是私有的,這樣派生類的析構函數才能調用它。通常,基類的設計者不會知道在析構函數中應該執行什么樣的動作。
Discussion(討論)
See this in the Discussion section:參見討論章節:
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Sd-dtor.
Example, bad(反面示例)
struct Base { // BAD: implicitly has a public nonvirtual destructor
virtual void f();
};
struct D : Base {
string s {"a resource needing cleanup"};
~D() { /* ... do some cleanup ... */ }
// ...
};
void use()
{
unique_ptr p = make_unique();
// ...
} // p's destruction calls ~Base(), not ~D(), which leaks D::s and possibly more
Note(注意)
A virtual function defines an interface to derived classes that can be used without looking at the derived classes. If the interface allows destroying, it should be safe to do so.虛函數定義了派生類的接口,它可以在不關注派生類的情況下使用。如果接口允許對象,那么這個銷毀過程應該是安全的。
Note(注意)
A destructor must be nonprivate or it will prevent using the type:析構函數必須是非私有的,除了它不想被別人用。(這樣可以由類自己控制銷毀,譯者注)
class X {
~X(); // private destructor
// ...
};
void use()
{
X a; // error: cannot destroy
auto p = make_unique(); // error: cannot destroy
}
Exception(例外)
We can imagine one case where you could want a protected virtual destructor: When an object of a derived type (and only of such a type) should be allowed to destroy another object (not itself) through a pointer to base. We haven't seen such a case in practice, though.我們可以想象一種需要保護的虛函數析構函數的情況:當希望允許派生類的對象(只有這個類型)通過基類指針銷毀另外一個對象(不是它自己)時。但是我們還沒有在實際的開發中遇到這種情況。
Enforcement(實施建議)
- A class with any virtual functions should have a destructor that is either public and virtual or else protected and nonvirtual.
- 擁有虛函數的類的虛函數要么是公開的虛函數,要么是保護的非虛函數。
譯者注:擁有虛函數一般就意味著它有派生類。
原文鏈接:
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c35-a-base-class-destructor-should-be-either-public-and-virtual-or-protected-and-nonvirtual
覺得本文有幫助?請分享給更多人。
更多文章請關注微信公眾號【面向對象思考】!
面向對象開發,面向對象思考!