如何删除没有虚析构函数的多态类类型的对象

时间:2012-10-21 04:12:33

标签: c++ inheritance destructor

当我尝试从第三方SDK编译某些代码时,我收到以下错误。

*Description    Resource    Path    Location    Type
deleting object of polymorphic class type ‘Vendor_sys::VendorCode’ which has non-virtual destructor might cause undefined behaviour [-Werror=delete-non-virtual-dtor]   PnServer.cpp    /PCounter   line 467    C/C++ Problem*

我不知道是否可以通过对Vendor SDK的部分了解来满足这一条件,其中大部分繁重工作都是在dll或库对象中完成的。

我的构建环境是Eclipse Juno with gpp。

我在Google中搜索了错误消息,但未找到此错误的任何实例。

因此,如果我无法修改供应商代码的黑盒部分,我的选择是什么?

以下是制作过程中失败的代码:

delete pData->unit;

6 个答案:

答案 0 :(得分:11)

坏消息,我很害怕。您不应该将该类用作基类。太多的限制和陷阱。你可能会逃避它,但为什么要冒风险呢?向库供应商提交错误报告。

如果您不需要多态指针,请在您的类中包含该类型的对象,并委托您想要继承的成员函数。

class my_class {
private:
    evil_class evil;
public:
    virtual ~my_class() {/* stuff */}
    virtual int member() { return evil.member(); }
};

答案 1 :(得分:8)

这是第三方SDK中的一个错误。任何用作基类的类都应该有一个虚析构函数。否则,当您删除指向派生类实例的基础的指针时,将不会调用派生类的析构函数。

一种方法是不删除指向基础的指针。相反,使用dynamic_cast来获取指向派生类的指针(如果有许多类派生自该基类,这可能会很不方便)。

答案 2 :(得分:3)

当基类具有虚拟成员函数但没有虚拟dtor时,会产生此警告。这是一个错误。如果您没有代码,那么除了确保您手动取消分配子类中的任何资源之外,您无能为力。就像在自定义cleanup()成员函数中一样,您确保在删除对象之前手动调用。

另一个选择是static_cast到正确的班级。请注意,不需要dynamic_cast(导致运行时开销并需要RTTI)。在这种情况下,编译器可以在编译时很好地派生类型关系。

当然,如果将对象删除到其他不属于您代码的地方,那么您就不走运了。在这种情况下,请确保您的子类不分配任何内容。这样,即使没有调用析构函数,也不可能泄漏。

答案 3 :(得分:2)

除非在基类上声明了虚拟析构函数,否则无法安全地使用指向基类的指针。由于这是供应商库,因此无法添加所需的虚拟析构函数。

如果库本身不创建此对象的子类,则可以通过声明此对象的子类并将该对象用作基类来获得所需的效果。

class NotGoodBase {
 ~NotGoodBase(); // Non-virtual destructor.  Possibly added by compiler.
};

class UseThisAsBase : public NotGoodBase {
 virtual ~UseThisAsBase(); // Virtual destructor.
};

您应该可以在任何可以使用NotGoodBase的地方使用UseThisAsBase类型的指针,除非您需要具有类型为NotGoodBase的LValue,例如赋值或通过引用传递变量。

答案 4 :(得分:0)

在这种情况下,您需要向类中添加虚拟析构函数,而不是从此处删除编译标志。

例如。对于班级Myclass,此错误即将发生,然后添加

virtual ~Myclass(){}

试试这个灵魂,它会正常工作。

答案 5 :(得分:-3)

实际上,我从编译和程序编译中删除了-Werror开关。

现在,消息只是警告。

我会向供应商发送错误报告。