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

时间:2012-01-06 20:52:58

标签: 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); }
  };

有编译警告

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

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

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

#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(){}
  };

3 个答案:

答案 0 :(得分:77)

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

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

#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
}

输出:

Destructor of FooBase
Destructor of Bar
Destructor of BarBase

请注意,delete bar;会导致调用析构函数~Bar~BarBase,而delete foo;只调用~FooBase。后者甚至是undefined behavior,因此无法保证效果。

答案 1 :(得分:14)

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

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

将其关闭 会导致未定义的行为,通常会在valgrind等工具中显示为内存泄漏。

答案 2 :(得分:2)

它仅仅意味着像

这样的代码
CPolygon* p = new CRectangle;
delete p;

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

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