我的问题是您认为下面显示的代码是否安全?这样的代码可以生成运行时故障,例如:
__PureVirtualCalled() at 0x9000000007ef90c?
顺便说一下,我在GNU Linux(64位)上使用g ++ 4.3.2编译了这段代码。输出是:
~derived called. ~base() called. ~base() called. foo() called.
请注意,下面给出的代码只是我编写的一个小程序来解释问题。真正的类实际上是一个引用计数器的实现,只有当它的计数降到零时才会自行处理。手动调用析构函数的原因是为了避免虚函数调用的开销(引用计数器类派生自抽象计数器类)。可以通过显式指定要调用的函数来抑制虚拟调用,尤其是在类是派生最多的函数时。但是,这显然不适用于虚拟析构函数。
另外一个信息,得到上述错误的真正应用程序是一个多线程应用程序。
请注意,我试图解释为什么运行时会引发上述错误。它间歇性地这样做。
代码
#include <iostream>
class base {
public:
virtual ~base() {
std::cout << "~base() called." << std::endl;
}
virtual void dispose() = 0;
void foo() {
dispose();
std::cout << "foo() called." << std::endl;
}
};
class derived : public base {
public:
~derived() {
std::cout << "~derived called." << std::endl;
}
void dispose() {
// Intention here is to suppress the virtual function call.
this->derived::~derived();
delete this;
}
};
int main() {
base* ptr = new derived;
ptr->foo();
return 0;
}
答案 0 :(得分:4)
我不确定你要做什么,但是......
行:
this->derived::~derived();
delete this;
导致未定义的行为。首先你明确地破坏了
对象,然后你调用delete
,它调用析构函数
什么有效地成为原始记忆。 delete this;
应该够了。您唯一要明确调用的时间
析构函数是在分配和初始化时,
在这种情况下,您将使用placement new来构建
物体。