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

C++ 如何删除没有虚拟析构函数的多态类类型的对象,c++,inheritance,destructor,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] PnS

当我试图从第三方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*

我不知道如果只了解供应商SDK的一部分就可以满足这个条件,其中大部分繁重的工作都是在dll或库对象中完成的

我的构建环境是带有gpp的EclipseJuno

我在谷歌上搜索了错误信息,但没有找到这个错误的任何实例

那么,如果我不能修改供应商代码的黑盒部分,我的选项是什么

以下是生成过程中失败的代码:

delete pData->unit;

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


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

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

另一个选项是
static\u cast
将其转换为正确的类。请注意,不需要
dynamic_cast
(这会产生运行时开销并需要RTTI)。在这种情况下,编译器可以在编译时很好地派生类型关系


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

恐怕是坏消息。不应将该类用作基类。太多的限制和陷阱。你可能会侥幸逃脱,但为什么要冒险呢?向库供应商提交错误报告

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

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

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

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

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

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

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

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

现在,这些信息只是警告


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

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

例如,对于class
Myclass
这个错误即将出现,然后添加

virtual ~Myclass(){}

试试这个解决方案,它会工作得很好。

那么这个类是从继承来的,但没有虚拟析构函数?我会向图书馆的建造者抱怨的。警告有点温和。通过指向没有虚拟析构函数的基类型的指针删除派生类型的对象会导致未定义的行为。没有关于它的“可能”。@PeteBecker至少在g++4.8中发出了这个警告,即使我通过指向派生类的指针删除了它。这是安全的(AFAIK),所以这里的“可能”也是错误的(警告根本不应该生成)。我猜g++无法区分这两种情况。@彼得贝克在我的例子中,它当然可能是一个进一步的派生类(在这种情况下,警告是正确的),但这种情况永远不能(IMHO)被排除在外;如果基类型没有虚拟析构函数,则通过指向基的指针删除派生类型的对象具有未定义的行为。当然,没有虚拟函数意味着不太可能有人摆弄指向基类型的指针。@PeteBecker GCC不会在没有虚拟函数时发出警告。问题仍然存在,但没有任何警告。C++在2011标准之前没有<代码>最终< /Cord>关键字,因此假设没有虚拟函数的类不应该继承。如果是这样的话,那就是老年退休金计划的错误。在这种情况下,这是SDK的错误。我只是想指出,“假设”隐藏了很多模糊性。C++标准中有几个类没有虚拟函数,但它们被用作基类。例如,模板类迭代器为其派生类型提供了一些typedef。只要您不试图通过指向迭代器的指针删除派生类型的对象,这就不是问题。一些警告是关于编译器编写者的想法,即我不够聪明,无法使用定义良好且意义明确的语言功能。我没有从所讨论的类创建任何子类。实际上,他可能能够在头文件中添加虚拟析构函数。哈克,哈克,克鲁格。这取决于是否在那里声明了一个,但没有在那里定义。根据我的说法,这不是正确的方法,你不应该仅仅为了让你的代码编译而更改编译标志,除非没有其他正确的方法,否则这应该被标记为答案