关于虚析构函数的一个问题
2011-09-26 17:43
162 查看
关于虚析构函数的一个问题(vc6.0)
effective c++中14条:基类的析构函数应该为虚函数
一般的:
5和6可以看做是4的分解步骤。
2和3都不为虚函数,则4只会析构Base部分,但不会报错;2和3都为虚构函数,则4可以调用Drived类的析构函数;2不为虚析构函数,3为虚析构函数,则4则会出错;2不为虚函数,3为虚函数,而1为虚函数,则执行4编译器不会报错,只会有内存泄露。
根据以上,编译器报错应该和虚函数表的构建有关。基类有虚表时,析构函数不为虚,派生类为虚,则不错报错,执行4有内存泄露。而且delete可分解为5和6步,2不为析构函数,3为析构函数,则4则会出错则是出现在6步,而5步仍可执行。operator delete和虚表的创建过程之间的影响产生了这个问题。
虚函数是通过虚表实现的,派生类的对象的头四个结点为虚表指针,指向虚表。构建对象时先构建基类,基类的虚函数加入虚表,再构建派生类数据,派生的虚函数加入虚表,派生类覆盖基类的虚函数则替代基类的虚表中的虚函数指针。通过虚表,最终实现了多态。
虚表方面知识参考:http://www.douban.com/group/topic/10733547/
在2不为虚析构函数,3为虚析构函数时,调用4时,通过下面程序:
d的结果为0x00380FE0,而b的结果为0x00380FE4,说明b和d指针是指向不同地方的,d指针指向从虚表开始,而b指针则跳过了虚表。这样5调用delete的时候,他类型类Base*,且基类没有虚析构函数,因此首先会调用pB->~Base(),之后编译器发现该指针指向派生类,而派生类对象中有虚表(pB指针当前不是指向虚表地址),编译器就会将这种情况和动态绑定情况混淆而前面已经调用了基类的析构函数,因此编译器会报错。这就解释了为什么1为虚函数,编译器同样不报错的原因,注意这时同同样不会调用派生类的析构函数,内存会泄露,因为基类本身就不是虚析构函数。
effective c++中14条:基类的析构函数应该为虚函数
一般的:
class Base { public: void fun(){} //1 ~Base() //2 { cout << "Base" << endl; } } class Drived : public Base { public: ~Drived() //3 { cout << "Drived" << endl; } } Base *pB = new Drived; delete pB; //4 //pB->~Base(); //5 //operator delete(pB); //6,清除内存
5和6可以看做是4的分解步骤。
2和3都不为虚函数,则4只会析构Base部分,但不会报错;2和3都为虚构函数,则4可以调用Drived类的析构函数;2不为虚析构函数,3为虚析构函数,则4则会出错;2不为虚函数,3为虚函数,而1为虚函数,则执行4编译器不会报错,只会有内存泄露。
根据以上,编译器报错应该和虚函数表的构建有关。基类有虚表时,析构函数不为虚,派生类为虚,则不错报错,执行4有内存泄露。而且delete可分解为5和6步,2不为析构函数,3为析构函数,则4则会出错则是出现在6步,而5步仍可执行。operator delete和虚表的创建过程之间的影响产生了这个问题。
虚函数是通过虚表实现的,派生类的对象的头四个结点为虚表指针,指向虚表。构建对象时先构建基类,基类的虚函数加入虚表,再构建派生类数据,派生的虚函数加入虚表,派生类覆盖基类的虚函数则替代基类的虚表中的虚函数指针。通过虚表,最终实现了多态。
虚表方面知识参考:http://www.douban.com/group/topic/10733547/
在2不为虚析构函数,3为虚析构函数时,调用4时,通过下面程序:
Drive *d = new Drive; Base *b = d; cout << d << endl; cout << b << endl;
d的结果为0x00380FE0,而b的结果为0x00380FE4,说明b和d指针是指向不同地方的,d指针指向从虚表开始,而b指针则跳过了虚表。这样5调用delete的时候,他类型类Base*,且基类没有虚析构函数,因此首先会调用pB->~Base(),之后编译器发现该指针指向派生类,而派生类对象中有虚表(pB指针当前不是指向虚表地址),编译器就会将这种情况和动态绑定情况混淆而前面已经调用了基类的析构函数,因此编译器会报错。这就解释了为什么1为虚函数,编译器同样不报错的原因,注意这时同同样不会调用派生类的析构函数,内存会泄露,因为基类本身就不是虚析构函数。
相关文章推荐
- 欢迎大家讨论一个关于界面显示的问题!!
- 请教一个关于url重写的问题
- 关于eclipse进行web开发tomcat启动失败的一个问题
- ASP.NET中一个简单的关于Session的问题的解决
- 记一个关于volatile作状态标志的很奇怪的问题
- 关于mule中Spring使用中的一个问题
- 一个关于文件下载的问题
- Spring中关于classpath:和classpath*:前缀的一个小问题
- 关于字典中可迭代的一个问题
- c++的getline一个关于缓冲区的一个小问题
- 一个关于无边框拉大小的问题
- Android关于一个页面双列表内嵌gridview单选问题
- 一个关于 imageView 设置 scaleType 的问题
- 关于修复VS2008提示加载安装组件出现问题和点击VS的设计窗口出现一个WINDOW installer的提示的问题的解决办法
- 一个关于TreeView拖动的问题
- 关于ViewPager Activity的一个问题
- 一个关于类中self的问题
- 关于struts的一个验证的一个问题
- 关于从VSS 中打开一个含有Web工程的方案时的问题—以前原创(三)
- 一个关于ConfigurationManager.GetSecion方法的小问题