VC语言

本类阅读TOP10

·VC++ 学习笔记(二)
·用Visual C++打造IE浏览器(1)
·每个开发人员现在应该下载的十种必备工具
·教你用VC6做QQ对对碰外挂程序
·Netmsg 局域网聊天程序
·Windows消息大全
·VC++下使用ADO编写数据库程序
·VC++学习笔记(四)
·非法探取密码的原理及其防范
·怎样在VC++中访问、修改注册表

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
你需要virtual析构函数吗

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

你需要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析构函数的效果。




相关文章

相关软件