是否有用于使受保护的析构函数虚拟化?

tus*_*oyd 10 c++ inheritance protected virtual-destructor

/*Child is inherited from Parent*/
class Parent {  
  public:  
    Parent () //Constructor
    {
        cout << "\n Parent constructor called\n" << endl;
    }
  protected:
    ~Parent() //Dtor
    {
        cout << "\n Parent destructor called\n" << endl;
    }
};

class Child : public Parent 
{
  public:
    Child () //Ctor
    {
        cout << "\nChild constructor called\n" << endl;
    }
    ~Child() //dtor
    {
        cout << "\nChild destructor called\n" << endl;
    }
};

int main ()
{
    Parent * p2 = new Child;          
    delete p2;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我将Parent析构函数设为虚拟,那么我会得到一个错误,那么将受保护的析构函数设为虚拟的目的是什么?

Mar*_*ner 18

举一个例子:假设您有一个实现引用计数的基类.你有一个addRef和一个release方法,你希望你的对象被销毁,如果(并且只有)内部计数器通过调用达到零release.

所以,首先你要保护你的析构函数(因为你只想从内部销毁对象relase).

如果你打算从你的类派生,你也希望你的析构函数是虚拟的,因为你需要一个虚拟的析构函数,只要你想通过指向基类的指针来销毁子对象(感谢@sharptooth提示......)

  • 不,您需要一个虚拟析构函数,无论派生类是否需要任何额外的破坏,否则行为只是未定义. (3认同)
  • @MartinStettner 请参阅我的答案:受保护的析构函数不需要是虚拟的。 (2认同)

sha*_*oth 5

是的,如果你打算做delete thisclass Parent成员函数执行时,这是很常见IUnknown::Release()的COM对象.


Ale*_*mez 5

在C ++核心准则条目专门为这个特定的主题:

C.35:基类的析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的

原因防止未定义的行为。如果析构函数是公共的,则调用代码可以尝试通过基类指针破坏派生的类对象,如果基类的析构函数是非虚拟的,则结果不确定。如果析构函数受到保护,则调用代码无法通过基类指针进行销毁,并且析构函数不需要是虚拟的。它确实需要受到保护,而不是私有的,以便派生的析构函数可以调用它。通常,基类的编写者不知道在破坏时要采取的适当措施。

因此,如果析构函数受到保护,则不需要是虚拟的。但是,有一个例外:

异常我们可以想象一种情况,当您需要一个受保护的虚拟析构函数时:当应该允许派生类型的对象(并且只有这种类型的对象)通过指向基址的指针销毁另一个对象(而不是自身)时。不过,实际上我们还没有看到这样的情况。

因此,总而言之,实际上,受保护的析构函数不需要是虚拟的。