虚析构函数作用分析(转)

来源:互联网 发布:mysql 删除某一字段 编辑:程序博客网 时间:2024/06/10 09:36

1.虚函数的实现原理:

实现虚函数需要对象附带一些额外信息,以使对象在运行时可以确定该调用哪个虚函数。对大多数编译器来说,这个额外信息的具体形式是一个称为vptr(虚函数表指针)的指针。vptr指向的是一个称为vtbl(虚函数表)的函数指针数组。每个有虚函数的类都附带有一个vtbl。当对一个对象的某个虚函数进行请求调用时,实际被调用的函数是根据指向vtbl的vptr在vtbl里找到相应的函数指针来确定的。

2.构造函数不可以是virtual的

构造函数不能用虚拟,因为用也没用,不管是在栈上构造对象,还是在堆上构造对象,也不管你以后是否使用父类的指针或引用来指向或引用这个对象,在构造的那“一瞬间”,总归要指明要构造对象的具体类型,所以,对象在构造过程中不存在运行时动态绑定的多态行为。 
你理解这个意思吗?举了例子就明白了,通常,假如A是B的父类, 
A* p = new B(); 
则对于虚拟函数f,可以通过A类的指针p直接调用到B类的函数,这就是运行时的多态: 
p->f(); 
但你注意没有,B类的对象却必须通过“A* p = new B();”来构造,显然不能通过“A* p = new A();”来构造一个B类对象——这是荒唐的,这只能构造一个A类的对象。所以构造函数虚拟无意义。 

3.析构函数应该是virtual的

但析构函数就不同了,p明明是个A类的指针,如果析构函数不是虚拟的,那么,你后面就必须这样才能安全的删除这个指针: 
delete (B*)p; 
但如果构造函数是虚拟的,就可以在运行时动态绑定到B类的析构函数,直接: 
delete p; 
就可以了。这就是虚析构函数的作用。而事实上,在运行时,你并不是总是能知道p所指对象的实际类型从而进行强制转换,所以,C++语言既然要支持多态,也就必须支持虚拟析构。

 

4.可以看出虚析构函数跟一般的虚函数没有什么不同,一般情况下通过pBase->func();来调用,实现动态绑定;CBase *pBase=new CDerive;

delete pBase;如果这时析构函数不是虚拟的显然就不可能去调用派生类的析构函数了,如果这时候在派生类中的析构函数中需要释放一些对内存,这时候就会出现内存泄露的情况。

5.还有一点值得注意的是若是纯析构函数,则必须提供纯析构函数的定义

这个定义是必需的,因为虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。这就是说,即使是抽象类,编译器也要产生对~awov的调用,所以要保证为它提供函数体。如果不这么做,链接器就会检测出来,最后还是得回去把它添上。


原创粉丝点击