在某种情况下,派生类是否合法拥有非virtual析构函数?非virtual析构函数表示不应将类用作基类.具有virtual派生类的非析构函数是否会像Java final修饰符的弱形式一样?
我特别感兴趣的是派生类的基类有一个virtual析构函数.
In *_*ico 71
在某种情况下,派生类具有非虚拟析构函数是合法的吗?
是.
非虚析构函数表示不应将类用作基类.
并不是的; 非虚析构函数表示derived通过base指针删除实例将不起作用.例如:
class Base {};
class Derived : public Base {};
Base* b = new Derived;
delete b; // Does not call Derived's destructor!
Run Code Online (Sandbox Code Playgroud)
如果你不delete按上述方式做,那就没关系了.但如果是这种情况,那么你可能会使用组合而不是继承.
具有派生类的非虚析构函数是否会像Java final修饰符的弱形式一样?
不,因为virtual-ness传播到派生类.
class Base
{
public:
virtual ~Base() {}
virtual void Foo() {};
};
class Derived : public Base
{
public:
~Derived() {} // Will also be virtual
void Foo() {}; // Will also be virtual
};
Run Code Online (Sandbox Code Playgroud)
C++ 03或更早版本中没有内置语言机制来防止子类(*).无论如何,这不是什么大问题,因为你应该总是喜欢组合而不是继承.也就是说,当"is-a"关系比真正的"has-a"关系更有意义时,使用继承.
(*)'final'修饰符是在C++ 11中引入的
Alo*_*ave 30
如果您永远不会在指向派生类对象的Base类指针上调用delete,那么使用非虚拟析构函数的Base类是完全有效的.
准则#:仅当派生类需要调用虚函数的基本实现时,才能使虚函数受到保护.仅针对析构函数的特殊情况:
准则#:基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的.
也许您的问题实际上是:如果Base类Destructor是虚拟的
,Derived类中的Destructor是否需要是虚拟的?
答案是否定的.
如果Base类析构函数是虚拟的,那么Derived类析构函数已经隐式虚拟,您不需要将其明确指定为虚拟.
Dav*_*eas 12
解决最新编辑:
编辑:我对派生类的基类有一个虚析构函数的情况特别感兴趣.
在这种情况下,无论是否添加关键字,派生类的析构函数都将是虚拟的virtual:
struct base {
virtual ~base() {} // destructor is virtual
};
struct derived : base {
~derived() {} // destructor is also virtual, because it is virtual in base
};
Run Code Online (Sandbox Code Playgroud)
这不仅限于析构函数,如果在类型层次结构中的任何一点将函数成员声明为虚拟,那么同一函数的所有重写(不重载)都将是虚拟的,无论它们是否被声明为.析构函数的特定位是~derived() 覆盖, virtual ~base()即使成员的名称不同 - 这是析构函数的唯一特性.
您的问题还不清楚。如果基类具有虚拟析构函数,则派生类将具有一个虚拟析构函数。声明虚拟化后,无法将其关闭。
当然,在某些情况下,从没有虚拟析构函数的类派生是有意义的。基类析构函数应该是虚拟的,以便您可以通过指向基类的指针进行删除。如果派生是私有的,则不必担心,因为您Derived*不会将其转换为Base*。否则,我看到了以下建议:如果基类析构函数不是虚拟的,则应该对其进行保护;这样可以防止发生一种未定义行为(通过指向基数的指针删除)的情况。但是实际上,许多基类(例如
std::iterator<>)的语义使得任何人甚至都不会创建指向它们的指针。更不用说通过此类指针删除了。因此,添加保护可能比投入更多的精力。