C ++和虚拟析构函数

时间:2011-11-24 21:32:17

标签: c++ memory-management virtual new-operator

我正在一个应用程序中编写一个实用程序类,在这个应用程序中,它们可能是也可能不是将来的派生。我没有任何虚函数(使用虚拟dtors的一般准则),所以考虑到我的内存限制,我选择在这个实用程序类中没有虚拟析构函数。

一些程序员后来 - 有人通过派生来增加我的实用程序类。现在,如果在代码中的任何地方我的new'd和删除正确的dtor的新类将不会被调用,因为基类dtor不是虚拟的(参见示例代码)。

除了返回并更改基类之外 - 在这种情况下有什么解决方案?

#include <iostream>
using namespace std;

class utility {
  int i, j;

  public:
    utility () { cout << "utility ctor\n";};
   ~utility () { cout << "utility dtor\n";};
    void dosomething () { cout << "haha\n";};
};

class addtoutility: public utility  {
  char *ch;

  public:
   addtoutility () { ch= new char(); cout << "added ctor\n";};
  ~addtoutility () { delete ch; cout << "added dtor\n";};
   void andnowaddsomefunctionality () {};
};

int main () {
  utility *u  = new addtoutility();
  //lots of interesthing code
  delete u;
}

3 个答案:

答案 0 :(得分:6)

您的基类不是多态的,因此在任何情况下都没有指向基类的值。您的基类通过不在任何地方使用virtual关键字来记录它不是多态的事实。

如果有人想将它用作多态层次结构的基类,那么他们可以将virtual析构函数添加到它们从中派生的第一个类中,并在必要时保存指向该基类类型的指针。 / p>

你不能阻止后来的程序员挖掘他们自己的陷阱,但非多态的类没有任何问题,你不需要做任何事情来“安全”。

作为这是常见且可接受的做法的证据,您只需要查看标准库。有许多类(严格来说,大多数是类模板),没有虚函数,也没有虚析构函数。

答案 1 :(得分:3)

  • 通过正确类型的指针删除它。由于没有其他方法是虚拟的,所以没有必要对其进行多态处理。

使用:

addtoutility *u  = new addtoutility();

delete u;
  • 将其设为虚拟。如果您担心开销,那么可能会忽略不计。
  • 使用CRTP使用静态继承。唯一的问题是,这可能比vtable占用更多的内存。

答案 2 :(得分:-1)

如果根本无法修改基类的代码,可以向派生类添加一个函数,如Destroy()。有点讨厌,但是如果你想到像Brush这样的Win32对象,我们会一直这么做。