强制虚拟析构函数? C++
我在 C++ Faq lite: How do I Define a base class so every class inheriting it is required to Define a destructor? 中没有看到这个问题的答案:
How do I Define a base class so every class inheriting it is required to Define a destructor?
我尝试运行这个程序
struct VDtor { virtual ~VDtor()=0; };
struct Test:VDtor { virtual ~Test(){} };
int main() { delete new Test; return 0; }
http://codepad.org/wFcE71w3 出现错误
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()'
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()'
那么,这可能吗?
I didn't see the answer to this in the C++ Faq lite:
How do I define a base class so every class inheriting it is required to define a destructor?
I tried running this program
struct VDtor { virtual ~VDtor()=0; };
struct Test:VDtor { virtual ~Test(){} };
int main() { delete new Test; return 0; }
http://codepad.org/wFcE71w3
With the error
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()'
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()'
So, is it possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从某种意义上说,这是“可能的”(如果您的目标是派生类保持抽象,否则)。但它不会给出您想要的结果:因为如果程序员没有这样做,编译器将隐式地创建析构函数本身。
因此不可能强制派生类的作者显式声明构造函数。
(编辑:就像@chubsdad
notes指出的那样,您的特定代码中的错误是因为您需要定义基类的显式声明的析构函数)。编辑< /strong>:只是为了好玩,有些情况需要显式声明的构造函数。考虑以下
代码此代码将无法编译,因为隐式声明的
~Derived
将具有比~Base
更宽松的异常规范throw (Dose)
code> 有 - 所以它违反了覆盖者不得有更宽松的异常规范的要求。您需要适当地显式声明析构函数但这并不是真正解决您的问题,因为派生类需要“合作”从
Viral
派生或将其作为非静态数据成员。它也非常丑陋:)编辑:以下似乎是一种符合标准的 Clang 和 GCC 方法
(从 v4.6 开始)拒绝任何具有隐式声明析构函数的
Base
派生类,因为它具有不兼容的异常规范(标准规定,任何派生类都应直接调用~Viral
,而不是通过调用~Base
间接调用)。科莫接受这一点,但我强烈怀疑它在这方面不符合规定。It is "possible" in some sense (if your goal was that the derived class stays abstract otherwise). But it won't give the result you would like: Because the compiler will create a destructor itself implicitly if the programmer hasn't done so.
It's therefor not possible to force the derived class' author to explicitly declare a constructor.
(edit: Like @chubsdad
notesnoted, the error in your particular code is because you need to define the explicitly declared destructor of the base class).Edit: Just for fun, there are situations that necessiate an explicitly declared constructor. Consider the following
This code won't compile because the implicitly declared
~Derived
will have an exception specificationthrow (Dose)
which is looser than what~Base
has - so it violates the requirement that overriders shall not have a looser exception specification. You will need to explicitly declare the destructor appropriatelyBut this is not really a solution to your problem, because derived classes need to "cooperate" into either deriving from
Viral
or putting it as a non-static data member. It's also very ugly :)Edit: The following seems to be a Standard conforming way to do it
Clang and GCC (starting with v4.6) reject any derived class of
Base
that has an implicitly declared destructor, because it has an incompatible exception specification (any derived class shall call~Viral
directly, instead of indirectly by calling~Base
, the Standard says). Comeau accepts this, but I strongly suspect that it is non-conforming in this regard.无论如何,每个类都有一个析构函数。在基础中声明虚拟析构函数可确保子级将拥有虚拟析构函数。这并不意味着编码人员需要显式声明析构函数——无论如何,这不是一件好事。它的意思是,如果声明了析构函数,它将是虚拟的。
Every class has a destructor, regardless. Declaring a virtual destructor in the base ensures that children will have virtual destructors. This doesn't mean that the coder will need to explicitly declare a destructor -- that wouldn't be a good thing, anyhow. All it means is that, if a destructor is declared, it will be virtual.
要修复该错误,您必须像上面一样实际实现 VDtor::~VDtor() 。
To fix the error you have to actually implement the VDtor::~VDtor() like above.
当 Test 被析构时,它将调用它的基类析构函数,该析构函数不存在。如果没有必要的销毁逻辑,您应该将其声明为空。
When Test is destructed, it will call it's base class destructor, which doesn't exist. You should just declare it empty if you have no necessary destruction logic.