17

我发现几乎每个虚拟析构函数的代码片段都将其作为公共成员函数,如下所示:

class Base
{
public:
    virtual ~Base()
    {
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    ~Derived()
    {
        cout << "~Derived()" << endl;
    }
};

虚拟析构函数是否必须是公共的,或者是否存在非公共虚拟析构函数有意义的情况?

4

5 回答 5

21

虚拟析构函数是否必须是公共的,或者是否存在非公共虚拟析构函数有意义的情况?

课程用马。如果您需要多态删除,则使用public虚拟析构函数,否则您的析构函数根本不需要是虚拟的。

听从Herb 的建议

准则 #4:基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。

简而言之,您将面临两种情况之一。任何一个:

  1. 您希望通过基指针允许多态删除,在这种情况下,析构函数必须是虚拟的和公共的;或者
  2. 您不需要,在这种情况下,析构函数应该是非虚拟的并受到保护,后者是为了防止不必要的使用。
于 2013-03-20T10:11:29.497 回答
6

就像非虚拟析构函数一样,它们不一定public,但大多数时候它们是。

如果您的类是规则的例外,并且出于任何原因需要控制其实例的生命周期,那么析构函数必须是非public. 这将影响客户端如何(或不能)利用类的实例,但这当然是重点。而且由于析构函数是virtual,唯一的其他选择是virtual protected

相关:将受保护的析构函数设为虚拟是否有用?

于 2013-03-20T09:58:58.330 回答
2

如果您计划通过特殊方法创建/销毁对象(例如,创建/销毁),则没有必要。但是,如果您在堆栈或堆上创建对象,则必须具有公共析构函数。

于 2013-03-20T09:58:23.913 回答
1

这里的问题是关于虚拟析构函数,因此我假设为什么需要这种实现的原因的排列也应该包括继承情况。问题的答案取决于以下几点:

1)如果您不希望类被实例化,您可以使用私有构造函数/析构函数。不过,实例化可以通过同一个类中的另一个方法来完成。所以,当你想在类中使用像 MyDestructor() 这样的特定方法来调用析构函数时,仍然可以将析构函数置于私有状态。例如:单例设计模式。此外,在这种情况下,它会阻止类被继承

2)如果打算继承所有类,则不允许私有基类析构函数(引发编译错误)。但是,受保护的基类析构函数允许继承

3)受保护的虚拟析构函数的继承类型(公共和受保护)允许安全的多级继承方式A->B->C,以便在调用C的析构函数时更好地清理内存。

4)当使用new动态分配内存时,单独的私有析构函数不能允许删除(我不确定auto_ptr,但我认为即使这样也应该遵守使用“私有”析构函数的相同想法)。

在周围,我看到使用私有析构函数可能容易出错,特别是当不知道这种实现的人即将使用这样的类时。

protected 和 public 析构函数总是受欢迎的,其使用取决于上面给出的需求。

希望这可以澄清。

于 2013-03-20T10:42:47.990 回答
0

这里涉及两个单独的规则。首先,如果您的设计要求通过指向基的指针删除派生类型的对象,则基中的析构函数必须是虚拟的。其次,如果一个成员函数(我广泛地包括析构函数)是受保护的或私有的,那么可以调用它的上下文比它是公共的(当然,如果析构函数是私有的,你可以) t 派生自类)。例如:

class C {
protected:
    virtual ~C();
    friend void destroy_me(C*);
};

void destroy_me(C *cp) {
    delete cp; // OK: destructor is accessible
}

void destroy_someone_else(C *cp) {
    delete cp; // Error: destructor is not accessible
}
于 2013-03-20T11:15:44.110 回答