在C++编译期间,"具有虚拟方法......但非虚拟析构函数"警告意味着什么?

qaz*_*wsx 39 c++ polymorphism virtual

#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); }
  };
Run Code Online (Sandbox Code Playgroud)

有汇编警告

Class '[C@1a9e0f7' has virtual method 'area' but non-virtual destructor
Run Code Online (Sandbox Code Playgroud)

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

[编辑]这个版本现在正确吗?(试图回答用这个概念来阐明自己)

#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(){}
  };
Run Code Online (Sandbox Code Playgroud)

Bjö*_*lex 78

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

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

#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
}
Run Code Online (Sandbox Code Playgroud)

输出:

Destructor of FooBase
Destructor of Bar
Destructor of BarBase
Run Code Online (Sandbox Code Playgroud)

请注意,只有调用时才会delete bar;导致析构函数~Bar和调用.后者甚至是未定义的行为,因此不能保证这种效果.~BarBasedelete foo;~FooBase

  • @HelloGoodbye看到这个问题:/sf/ask/19223851/ (2认同)

Tom*_*err 14

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

struct Foo {
  virtual ~Foo() {}
  virtual void bar() = 0;
};
Run Code Online (Sandbox Code Playgroud)

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

  • 离开它不是 - 本身 - 未定义的行为.它可能导致的唯一未定义行为是,如果使用`delete`表达式释放派生类型的动态分配对象,其中操作数的类型是指向基类的指针,其中基类没有虚拟析构函数.鼓励安全使用还有其他选项,例如为类提供受保护的非虚拟析构函数. (3认同)