你需要virtual析构函数吗

原创 2003年11月09日 22:02:00

你需要virtual析构函数吗

使用VC的class wizard自动生成一个类,会得到两个空的函数:构造函数和virtual析构函数。为什么析构函数要声明成virtual呢?

如果一个类要被使用成多态(polymorphic)的,那么这个virtual是必须的。比如:

#include <iostream>

class Animal
{
  char* ap;
public:
 
  Animal()
  {
    ap = new char;
    std::cout << "Animal ctor" << std::endl;
  }
  virtual void foo()
  {
    std::cout << "Animal::foo" << std::endl;
  }
  virtual ~Animal()
  {
    std::cout << "Animal dtor" << std::endl;
    delete ap;
  }
};

class Dog : public Animal
{
  char* dp;
public:
  Dog()
  {
    dp = new char;
    std::cout << "Dog ctor" << std::endl;
  }
  virtual void foo()
  {
    std::cout << "Dog::foo" << std::endl;
  }
  virtual ~Dog()
  {
    delete dp;
    std::cout << "Dog dtor" << std::endl;
  }
};

int main()
{
  Animal* pa = new Dog();
  pa->foo();
  delete pa;
  return 0;
}

delete pa 实际上相当于:
 pa->~Animal();
 释放pa所指向的内存(或许是free(pa))。
在这里,因为~Animal()是virtual的,尽管是通过Animal类型的指针调用的,根据v-table的信息,~Dog()被正确调用到。如果把virtual属性去掉,那么被调用的是~Animal(),Dog类的构造函数被调用而析构函数未被调用,构造函数中分配的资源没有释放,从而产生了内存泄漏。析构函数缺省声明为virtual,就可以避免这一问题。

可另一个问题是,有时virtual是不需要的。如果一个类不会被继承,比如一个utility类,该类完全是静态方法;或者一些类尽管可能会被继承,但不会被使用成多态的,即除了析构函数外,没有其他的方法是virtual的,这时就可以把virtual属性去掉。

去掉析构函数的virtual属性后,因为该类中没有其他的virtual函数,所以编译时不会生成v-table,这样就节省了编译时间,并减少了最终生成的程序的大小。更重要的是,遵从这一规则,给该类的维护者一个信息,即该类不应被当作多态类使用。

同样,当作一个抽象时,如果你模仿Java的interface,声明了如下的虚基类:

class AbstractBase
{
 virtual method1() = 0;
 virtual method2() = 0;
};

那么应该给它增加一个空的virtual析构函数:
 virtual ~AbstractBase(){}

如果你对COM比较熟悉,可能会注意到,COM interface中并没有这个virutal构造函数。这是因为,COM通过使用引用计数的机制来维护对象。当你使用完一个COM对象,调用Release()时,COM的内部实现检查引用技术是否为零。如果是,则调用
 delete this;
因为Release()是virtual的,所以该COM对象对应的正确的派生类被调用,delete this会调用正确的析构函数,达到了使用virtual析构函数的效果。

C++中基类的析构函数为什么要用virtual虚析构函数

C++中基类的析构函数为什么要用virtual虚析构函数, 弄清楚为什么。
  • IIcyZhao
  • IIcyZhao
  • 2013年09月22日 18:41
  • 4697

有继承的C++析构函数一定要用virtual

先补下virtual是啥 虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本。    先贴个代码,再解释 ...
  • ShiZhixin
  • ShiZhixin
  • 2015年07月16日 17:15
  • 784

C++析构函数后加上virtual的原因

C++析构函数加上virtual是为了防止内存泄漏。 用在C++实现多态的时候,其基类要加virtual。 原因跟动态绑定有关,大家都知道,多态是通过虚函数实现的,而虚函数又是通过动态绑定...
  • u014453898
  • u014453898
  • 2017年03月05日 01:51
  • 243

条款09 绝不在构造和析构过程中调用virtual函数

总结: 在构造或析构期间不要调用 virtual函数,因为这样的调用从不下降至派生类(比起当前执行构造函数和析构函数的那层)。        不应该在构造或析构期间调用 virtual函数,因为这...
  • u013074465
  • u013074465
  • 2015年02月04日 20:57
  • 1494

析构函数前加virtual关键字的作用?

大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态。那么把析构函数声明为vitual有什么作用呢?请看下面的代码: #include using namespace std...
  • sinat_20265495
  • sinat_20265495
  • 2016年06月28日 14:39
  • 1222

基类的析构函数为什么是virtual类型的

class CObject {    public: // Object model (types, destruction, allocation)    virtual CRuntime...
  • zxj88214
  • zxj88214
  • 2015年01月19日 10:21
  • 607

为什么析构函数要声明成virtual

(zz)为什么析构函数要声明成virtual   2011-03-08 15:43:00|  分类: reproduct|字号 订阅 为什么析构函数...
  • qiangwa0
  • qiangwa0
  • 2013年08月17日 21:06
  • 2074

C++ 析构函数以及 delete 和delete[]的整理

转自:http://hi.baidu.com/bystander1983/item/bf0b5c12b077cfec9913d651 delete和delete[] 的区别: C++告诉我们在回收...
  • qq_23363993
  • qq_23363993
  • 2016年08月15日 15:16
  • 1835

析构函数报错

析构函数在什么时候被调用执行?   对于C++程序员来说,这个问题比较简单,但是比较爱唠叨的阿愚还是建议应该在此再提一提,也算回顾一下C++的知识,而且这将对后面的讨论和理解由一定帮助。先看一个...
  • ghevinn
  • ghevinn
  • 2014年03月11日 11:06
  • 2837

在什么情况下把析构函数定义为私有的?

只能用new生成的对象 用new生成的对象,在面向对象中是很有用的.它保存在堆上,可以自由控制生命周期。 但如何保证一个对象只能在堆上生成呢? 答案其实也很简单,只需把析构函数定义为私有成员。例...
  • guyue35
  • guyue35
  • 2016年03月14日 20:29
  • 662
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:你需要virtual析构函数吗
举报原因:
原因补充:

(最多只允许输入30个字)