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
觉得本文有帮助?请分享给更多人。
更多文章请关注微信公众号【面向对象思考】!
面向对象开发,面向对象思考!