Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 虚拟析构函数必须是公共的吗?_C++_Destructor - Fatal编程技术网

C++ 虚拟析构函数必须是公共的吗?

C++ 虚拟析构函数必须是公共的吗?,c++,destructor,C++,Destructor,我发现几乎所有虚拟析构函数的代码片段都将其作为公共成员函数,如下所示: class Base { public: virtual ~Base() { cout << "~Base()" << endl; } }; class Derived : public Base { public: ~Derived() { cout << "~Derived()" << endl;

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

class Base
{
public:
    virtual ~Base()
    {
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    ~Derived()
    {
        cout << "~Derived()" << endl;
    }
};
类基
{
公众:
虚拟~Base()
{

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

就像非虚拟析构函数一样,不必使用公共析构函数,但大多数情况下它们都是公共的

如果您的类是该规则的例外,并且出于任何原因需要控制其实例的生存期,则析构函数必须是非
公共的
。这将影响客户端可以(或不能)执行的方式利用类的实例,但这当然是重点。由于析构函数是
虚拟的
,所以唯一的其他选项是
虚拟保护的

相关的:

虚拟析构函数必须是公共的,还是在某些情况下非公共虚拟析构函数才有意义?

马的路线。如果你需要多态删除,你使用一个
public
虚拟析构函数,如果不是,那么你的析构函数根本不需要是虚拟的

遵循

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

简言之,您将面临以下两种情况之一:

  • 您希望允许通过基指针进行多态删除,在这种情况下,析构函数必须是虚拟的和公共的;或者
  • 在这种情况下,析构函数应该是非虚拟的,并且受到保护,后者可以防止不必要的使用

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

    1) 如果不想实例化类,可以使用私有构造函数/析构函数。不过,实例化可以由同一类中的另一个方法完成。因此,当您想在类中使用特定方法(如MyDestructor())调用析构函数时,析构函数仍然可以置于私有之下。 例如:Singleton设计模式。同样,在这种情况下,它阻止类被继承

    2) 如果要继承该类,则不允许使用私有基类析构函数(抛出编译错误)。但是,受保护的基类析构函数允许继承

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

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

    综上所述,我发现使用私有析构函数可能容易出错,特别是当不知道这种实现的人即将使用这样的类时

    受保护和公共析构函数总是受欢迎的,其使用取决于上述需求


    希望能澄清这一点。

    这里涉及到两条独立的规则。首先,如果您的设计要求通过指向基的指针删除派生类型的对象,则基中的析构函数必须是虚拟的。其次,如果是成员函数(我通常包括析构函数)如果是protected或private,则可以调用它的上下文比它是public时受到更大的限制(当然,如果析构函数是private,则不能从类派生)。例如:

    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
    }
    

    @克里斯蒂安瑟林:我只是用了和问题一样的词。但是一个小的编辑会让事情变得更好,谢谢你的提示。而且(我想)您可以排除
    私有虚拟
    析构函数,因为带有私有析构函数的基类根本不能被销毁。私有析构函数对于不打算作为基类的类可能有意义,但如果它不是基类,那么它是虚拟的就没有意义。@SteveJessop:我也是这么认为的(“唯一的其他选项是
    虚拟受保护的
    ”)@Jon:是的,我正试图为那句话填充理由,也就是说,通过不提及它来明确地排除它,而不是含蓄地排除它:-)@StoryTeller,除了通过
    从派生类型删除这个
    ,这有时会使sense@ZdeslavVojkovic:
    在派生类中删除此
    不要求基类具有虚拟析构函数uctor,因为
    这个
    不是
    派生的
    中的
    基*
    类型。其他代码可能需要这种类型,ofc@SteveJessop,你是对的。我没有明确说明这是在继承链的上下文中说的,在继承链的上下文中,如果基一个是虚拟的,每个级别都可以调用
    安全地删除这个
    。@Storytler-你不能删除它如果您没有访问权限,请使用指向基的指针。将析构函数设置为受保护或私有并没有本质上的错误,但它限制了可以删除指针的人。@PeteBecker。我在哪里说过将析构函数设置为不可访问是错误的?但该建议假定您永远不希望允许通过基指针进行多态删除,rest对派生类进行了限制。考虑到问题是关于虚拟析构函数总是公开的动机,我认为Sutter在这里的论证中存在一个漏洞。例如,解释可能是,“派生类可以将基指针强制转换为正确的派生类型,然后将其删除。”“,但这本身就有一些假设。@SteveJessop:AFAIU,这是特别的建议,如果您需要多态删除,则析构函数必须是虚拟的,如果不是,则析构函数根本没有理由是虚拟的。其他情况是什么