首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么我要在C++中为抽象类声明一个虚拟析构函数?

为什么我要在C++中为抽象类声明一个虚拟析构函数?
EN

Stack Overflow用户
提问于 2008-11-07 00:55:30
回答 3查看 84.7K关注 0票数 172

我知道在C++中为基类声明虚拟析构函数是一种很好的做法,但是即使对于用作接口的抽象类,声明virtual析构函数也总是很重要的吗?请提供一些原因和例子。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2008-11-07 01:01:13

对于一个界面来说,这一点更加重要。您的类的任何用户都可能持有指向接口的指针,而不是指向具体实现的指针。当他们删除它时,如果析构函数是非虚的,他们将调用接口的析构函数(或者编译器提供的默认析构函数,如果您没有指定),而不是派生类的析构函数。即时内存泄漏。

例如

代码语言:javascript
复制
class Interface
{
   virtual void doSomething() = 0;
};

class Derived : public Interface
{
   Derived();
   ~Derived() 
   {
      // Do some important cleanup...
   }
};

void myFunc(void)
{
   Interface* p = new Derived();
   // The behaviour of the next line is undefined. It probably 
   // calls Interface::~Interface, not Derived::~Derived
   delete p; 
}
票数 205
EN

Stack Overflow用户

发布于 2008-11-07 01:01:39

是的,它总是很重要。派生类可能会分配内存或持有对其他资源的引用,这些资源在对象被销毁时需要清除。如果你没有给你的接口/抽象类提供虚拟析构函数,那么每次你通过基类句柄删除一个派生类实例时,你的派生类的析构函数将不会被调用。

因此,您打开了内存泄漏的可能性

代码语言:javascript
复制
class IFoo
{
  public:
    virtual void DoFoo() = 0;
};

class Bar : public IFoo
{
  char* dooby = NULL;
  public:
    virtual void DoFoo() { dooby = new char[10]; }
    void ~Bar() { delete [] dooby; }
};

IFoo* baz = new Bar();
baz->DoFoo();
delete baz; // memory leak - dooby isn't deleted
票数 11
EN

Stack Overflow用户

发布于 2012-12-27 22:27:55

答案很简单,你需要它是虚拟的,否则基类就不是一个完整的多态类。

代码语言:javascript
复制
    Base *ptr = new Derived();
    delete ptr; // Here the call order of destructors: first Derived then Base.

如果基类的析构函数不是虚的,那么只会调用基类的析构函数,派生类中的所有数据都不会被删除。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/270917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档