Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.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++;11';s已删除派生类中的析构函数_C++_C++11_Destructor - Fatal编程技术网

C++ C++;11';s已删除派生类中的析构函数

C++ C++;11';s已删除派生类中的析构函数,c++,c++11,destructor,C++,C++11,Destructor,cl test.cpp: class B { int i; public: B(int param) : i(param) {} ~B() = delete; }; class D : public B { int i2; public: D(int p1, int p2) : B(p1), i2(p2) {} ~D() = delete; }; int main() { B* instance = new D(1,2); ret

cl test.cpp:

class B {
    int i;
public:
    B(int param) : i(param) {}
    ~B() = delete;
};
class D : public B {
    int i2;
public:
    D(int p1, int p2) : B(p1), i2(p2) {}
    ~D() = delete;
};

int main() {
    B* instance = new D(1,2);
    return 0;
}
(代码上方有一个员工行,因此这些是一次性的。对不起)

我有一些特殊的类(一个基类和许多派生类),出于性能原因,这些类总是在堆栈式内存竞技场中分配。 它们不会得到任何析构函数调用(而且根据设计,它们也不需要)。如果我之后的一些程序员决定他真的需要在里面放一个向量,这可能会很糟糕。(内存泄漏,这些类大量生成,并且存在一些函数调用,哎哟)

我尝试的是使用C++11删除的析构函数。 我的问题是:

  • 为什么这不起作用
  • 有没有更好的办法来禁止类内的析构函数或非吊舱
为什么这不起作用

§12.6.2[基本类初始]/p10:

在非委托构造函数中,可能调用类类型的每个可能构造的子对象的析构函数(12.4)。[注:该规定确保在抛出异常时,可以为完全构造的子对象调用析构函数(15.2)。-结束注]

§12.4[类别dtor]/p11:

[…]如果可能被调用的析构函数被删除
或无法从调用上下文中访问,则程序是格式错误的

如果在任何子对象的构造过程中引发异常,编译器将调用已构造基类和数据成员的析构函数,因此
D
的构造函数需要
B
的非删除、可访问的析构函数

有没有更好的办法来禁止类内的析构函数或非吊舱

在您的情况下,让析构函数
受保护
应该可以工作:

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(11) : error C2280: 'B::~B(void)' : attempting to reference a deleted function
    test.cpp(6) : see declaration of 'B::~B'
Piotr已经解释了现有代码无效的原因。这里有一个替代方案

可以声明但不能定义基类析构函数:

class B {
    int i;
public:
    B(int param) : i(param) {}
protected:
    ~B() {}
};
class D : public B {
    int i2;
public:
    D(int p1, int p2) : B(p1), i2(p2) {}
protected:
    ~D() {}
};

通过这样做,现有代码将正常工作,任何试图破坏
B
实例的程序都将无法链接,因为
~B()
未定义。这并不十分理想(因为它给出的是链接时错误而不是编译时错误),但它可能会提供您所需的信息。

可能会有所帮助。快速完整的回答。谢谢。奇怪的是,标记
D
构造函数
noexcept
不允许将
~B
标记为已删除。如果编译器由于Piotr提到的原因引用析构函数,那么链接器将不得不解析该引用。@ArneMertz:D构造函数的
noexcept
状态似乎很重要。
class B {
    int i;
public:
    B(int param) : i(param) {}
    ~B();
};