在 C++ 编译期间,“具有虚拟方法......但非虚拟析构函数”警告是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8764353/
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-28 19:04:08  来源:igfitidea点击:

What does 'has virtual method ... but non-virtual destructor' warning mean during C++ compilation?

c++polymorphismvirtual

提问by qazwsx

#include <iostream>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    virtual int area ()
      { return (0); }
  };

class CRectangle: public CPolygon {
  public:
    int area () { return (width * height); }
  };

Has compilation warning

有编译警告

Class '[C@1a9e0f7' has virtual method 'area' but non-virtual destructor

How to understand this warning and how to improve the code?

如何理解这个警告以及如何改进代码?

[EDIT] is this version correct now? (Trying to give answer to elucidate myself with the concept)

[编辑] 这个版本现在正确吗?(试图给出答案以阐明自己的概念)

#include <iostream>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    virtual ~CPolygon(){};
    virtual int area ()
      { return (0); }
  };

class CRectangle: public CPolygon {
  public:
    int area () { return (width * height); }
    ~CRectangle(){}
  };

回答by Bj?rn Pollex

If a class has a virtual method, that means you want other classes to inherit from it. These classes could be destroyed through a base-class-reference or pointer, but this would only work if the base-class has a virtual destructor. If you have a class that is supposed to be usable polymorphically, it should also be deletable polymorphically.

如果一个类有一个虚方法,那就意味着你希望其他类继承它。这些类可以通过基类引用或指针销毁,但这只有在基类具有虚拟析构函数时才有效。如果你有一个应该多态可用的类,它也应该是多态可删除的。

This question is also answered in depth here. The following is a complete example program that demonstrates the effect:

这个问题也在这里得到了深入的回答。下面是一个完整的示例程序,演示了效果:

#include <iostream>

class FooBase {
public:
    ~FooBase() { std::cout << "Destructor of FooBase" << std::endl; }
};

class Foo : public FooBase {
public:
    ~Foo() { std::cout << "Destructor of Foo" << std::endl; }
};

class BarBase {
public:
    virtual ~BarBase() { std::cout << "Destructor of BarBase" << std::endl; }
};

class Bar : public BarBase {
public:
    ~Bar() { std::cout << "Destructor of Bar" << std::endl; }
};

int main() {
    FooBase * foo = new Foo;
    delete foo; // deletes only FooBase-part of Foo-object;

    BarBase * bar = new Bar;
    delete bar; // deletes complete object
}

Output:

输出:

Destructor of FooBase
Destructor of Bar
Destructor of BarBase

Note that delete bar;causes both destructors, ~Barand ~BarBase, to be called, while delete foo;only calls ~FooBase. The latter is even undefined behavior, so that effect is not guaranteed.

请注意,这delete bar;会导致调用析构函数~Bar~BarBase, 而delete foo;只调用~FooBase. 后者甚至是未定义的行为,因此无法保证效果。

回答by Tom Kerr

it means you need a virtual destructor on a base class with virtual methods.

这意味着您需要在具有虚拟方法的基类上使用虚拟析构函数。

struct Foo {
  virtual ~Foo() {}
  virtual void bar() = 0;
};

Leaving it off iscan lead to undefined behavior, usually shows up as a memory leak in tools like valgrind.

离开它关闭可能会导致不确定的行为,往往表现为在像Valgrind的工具内存泄漏。

回答by Emilio Garavaglia

It merely means that a code like

这仅仅意味着像这样的代码

CPolygon* p = new CRectangle;
delete p;

... or whatever wrapping into whatever smart pointer, will essentially not behave correctly since CPolygon is not polymorphic on deletion, and the CRectange part will not be destroyed properly.

...或任何包装到任何智能指针中的东西,基本上都不会正确运行,因为 CPolygon 在删除时不是多态的,并且 CRectange 部分不会被正确销毁。

If you're not going to delete CRectangle and CPolygon polymorphicaly, that warning is not meaningful.

如果您不打算多态地删除 CRectangle 和 CPolygon,则该警告没有意义。