受保护的析构函数 vs 私有的析构函数

36

在C++中,protected和private析构函数有何区别?如果基类的析构函数是private的,我想当删除派生类对象时它仍然会被调用。


4
您将会因为拥有私有析构函数的类而遇到一些问题 =) - SadSido
请为 https://dev59.com/mHRB5IYBdhLWcg3wa2m2 ? 创建副本。 - SadSido
1
类似的问题在这里:https://dev59.com/QnVC5IYBdhLWcg3wpS7g - Jordan
4个回答

33
如果基类的析构函数是私有的或受保护的,那么你无法通过基类指针调用 delete 操作。
使用受保护的析构函数可以防止通过基类指针销毁派生对象。它将析构函数的访问权限限制在派生类中,并且防止基类的自动(堆栈)对象。 实际上,它被用于允许通过基类指针进行其他多态使用的派生类,但不允许用户使用这样的指针删除对象。例如:抽象基类/接口。
但是,在非虚拟、非最终类上使用受保护的析构函数似乎会引发潜在问题。假设您没有提供 destroy() 函数,您必须最终将析构函数设置为公共的。一旦这样做,您就无法进一步控制该类,并且可能面临由于某人进一步从您的类派生而导致的非虚拟析构函数的多态删除的风险。

但是,一个受保护的非虚析构函数似乎是一个等待发生的错误,这似乎与核心指南相矛盾。 - agentsmith
添加了“非最终”的内容,这也是最初的意图。 - Abhay

28

引用自这里:

如果构造函数/析构函数被声明为private,则该类无法实例化。

尽管如此,该类可以从类中的另一个方法中实例化。同样,如果析构函数是private,那么对象也只能在类内部删除。此外,它防止了该类被继承(或者至少防止继承类被实例化/销毁)。


5
并不完全正确。 公共类A{私有A(){}公共A getA(){返回new A(); }} - Stefan Kendall
3
不是这样的。拥有私有析构函数的对象可以被实例化(例如,在友元函数中可以在栈上实例化)。 - SadSido
3
Right类型无法进行栈分配,但可以进行堆分配,同时可以在友元函数中对其进行分配。 - Brian R. Bondy
3
如果析构函数是受保护的,情况也是如此,因此这不会区分受保护和私有。 - Mike Seymour
4
缺失的事实:你可以使用 new 创建一个有私有析构函数的类,但是你不能在成员函数和友元函数之外使用 delete 删除它。 - Thomas Eding
关于析构函数的观点是错误的。在主函数中实例化具有私有/受保护析构函数的类不会有任何问题。 - LogicBreaker

11

以下代码会导致编译器错误(VC2010):C2248: 'base::~base' : 无法访问类“base”中声明的私有成员。

class base
{
    ~base(){}
};

class derived : public base
{
};

int main ()
{
    derived* d = new derived;

    delete d;
}

然而,如果你将基类析构函数改为protected(受保护的),一切都能正常工作。


2
但是即使你将它改为“protected”,你也无法通过基类指针销毁对象。(在这种情况下,它也应该是“virtual”。)这在某种程度上破坏了派生的许多目的... - sbi

6
答案是你的假设是错误的。当基类析构函数被声明为私有时,它将无法被调用。

那我的类怎么被销毁呢? - doron
2
@deus-ex-machina399:它是不可能的。因此,您无法从中派生出任何东西。您也无法创建自动对象。动态对象永远不能被删除(除非您提供一个成员函数来执行此操作)。 - sbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接