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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12994920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:52:00  来源:igfitidea点击:

How to delete an object of a polymorphic class type that has no virtual destructor

c++inheritancedestructor

提问by bentaisan

I am getting the following error when I try to compile some code from a Third-party SDK.

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


I do not know if its possible to satisfy this condition with only partial knowledge of the Vendor's SDK, where most of the heavy lifting is done in a dll or library object.

我不知道是否有可能仅通过对供应商 SDK 的部分了解来满足此条件,其中大部分繁重的工作都是在 dll 或库对象中完成的。

My build environment is Eclipse Juno with gpp.

我的构建环境是带有 gpp 的 Eclipse Juno。

I searched in Google for the error message and did not find any instances of this error.

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

So, if I cannot modify the black box part of the vendor code, what are my options?

那么,如果我不能修改供应商代码的黑匣子部分,我的选择是什么?

Here is the code that is failing during the make process:

这是在 make 过程中失败的代码:

delete pData->unit;

采纳答案by bentaisan

Actually, I removed the -Werror switch from the compile and the program compiled.

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

Now, the messages are just warnings.

现在,这些消息只是警告。

I will send a bug report to the vendor.

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

回答by Jive Dadson

Bad news, I am afraid. You should not use that class as a base class. Too many constraints and pitfalls. You might get away with it, but why risk it? File a bug report with the library vendor.

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

If you do not need polymorphic pointers, include an object of that type in your class, and delegate the member functions you wanted to inherit.

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

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

回答by user1610015

Well it's a bug in the third-party SDK. Any class that is used as a base class should have a virtual destructor. Otherwise, when you delete a pointer to the base of a derived class instance, the derived class's destructor won't be called.

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

One way around it is to not delete pointers to the base. Instead, use dynamic_cast to get a pointer to the derived class (this might be inconvenient if there are many classes derived from that base).

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

回答by Nikos C.

This warning is produced when the base class has virtual member functions but no virtual dtor. This is a bug. If you don't have the code, then there's nothing you can do other than making sure you're manually de-allocating any resources in your subclass. Like in a custom cleanup()member function that you make sure to call manually before deleting the object.

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

Another option is to static_castit to the correct class. Note that dynamic_cast(which incurs runtime overhead and requires RTTI) is not needed. The compiler can derive the type relationship just fine at compile time in this case.

另一种选择是将static_cast其分配给正确的类。请注意,dynamic_cast不需要(会产生运行时开销并需要 RTTI)。在这种情况下,编译器可以在编译时很好地导出类型关系。

Of course, if the object is deleted somewhere else that's not part of you code, then you're out of luck. In that case, make sure your subclass doesn't allocate anything. That way it's not possible to leak even when the destructor isn't being called.

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

回答by Greg Fisher

You cannot safely use a pointer to the base class, unless it has a virtual destructor declared on the base class. Since this is a vendor library, you can not add the virtual destructor needed.

您不能安全地使用指向基类的指针,除非它在基类上声明了一个虚拟析构函数。由于这是一个供应商库,您不能添加所需的虚拟析构函数。

If the library itself does not create subclasses of this object, you may be able to get the effect you need by declaring a subclass for this object and use that object as a base class.

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

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

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

You should be able to use pointers of type UseThisAsBase anywhere that you could use NotGoodBase, except places where you need to have an LValue of type NotGoodBase, such as an assignment or when passing a variable by reference.

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

回答by spt025

In this scenario you need to add virtual destructor to your class rather than removing compilation flag from here.

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

eg. for class Myclassthis error is coming then add

例如。对于类Myclass此错误即将到来然后添加

virtual ~Myclass(){}

Try this soultion, it will work fine.

试试这个灵魂,它会工作得很好。