构造函数调用虚函数的问题
一般情况下,不允许在构造函数或者析构函数中调用虚函数。其实语法上都没有问题,只是会失去多态性。
如果在构造函数中调用虚函数,会先调用父类中的实现,也就失去了多态的性质。
class A {public:virtual void print() {cout << "A" << endl;}A() {print();}~A() {//print(); } }; class B :public A {void print() {cout << "B" << endl;} }; int main() {A* ptr = new B;return 0; }
如果在析构函数中调用虚函数,也是同样的失去了多态性。
class A {public:virtual void print() {cout << "A" << endl;}A() {print();}~A() {print();} }; class B :public A {void print() {cout << "B" << endl;} }; int main() {A* ptr = new B;delete ptr;return 0; }
出现上述结果的原因是因为,构造函数还没有将vptr和vtable初始化完毕,就调用虚函数,此时必然调用的基类中的实现。
而在析构函数中,因为子类的那部分已经被析构掉了,此时在父类的析构函数调用虚函数,调用的也只能是父类中的实现。
但是吧,也有的文章说如果一个类为基类的时候,必须将析构函数写为虚函数,否则子类那部分无法释放。
https://blog.csdn.net/starlee/article/details/619827
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:
有下面的两个类:
class ClxBase
{
public:
ClxBase() {};
virtual ~ClxBase() {};
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase
{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
代码
ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;
的输出结果是:
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
这个很简单,非常好理解。
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
Do something in class ClxDerived!
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
转载于:https://www.cnblogs.com/LUO77/p/5907297.html
构造函数调用虚函数的问题相关推荐
- C++构造函数调用虚函数的后果
#include <iostream>class cx { public:virtual void func() {std::cout << "func" ...
- 构造函数调用虚函数先从子类搜索同名函数
1 class X 2 { 3 X() 4 { 5 System.out.println("x"); // 6 vir(44); //看到vir会先搜索子类中的vir是否存在,如果 ...
- C++构造函数和析构函数调用虚函数时都不会使用动态联编
先看一个例子: #include <iostream> using namespace std;class A{ public:A() {show();}virtual void show ...
- Effective C++(9) 构造函数调用virtual函数会发生什么
问题聚焦: 不要在构造函数和析构函数中调用virtual函数,因为这样的调用不会带来你预想的结果. 让我先来看一下在构造函数里调用一个virtual函数会发生什么结果 Demo class Trans ...
- C++构造函数与析构函数调用虚函数的注意事项
虽然可以对虚函数进行实调用,但程序员编写虚函数的本意应该是实现动态联编.在构造函数中调用虚函数,函数的入口地址是在编译时静态确定的,并未实现虚调用.但是为什么在构造函数中调用虚函数,实际上没有发生动态 ...
- python构造函数调用成员函数_成员函数中的Python调用构造函数
让我们以这个类为例,它正在扩展MySQLDB的connection对象.在class DBHandler(mysql.connections.Connection): def __init__(sel ...
- python构造函数调用成员函数_Python 子类构造函数调用
super作用 如果子类(Puple)继承父类(Person)不做初始化,那么会自动继承父类(Person)属性name. 如果子类(Puple_Init)继承父类(Person)做了初始化,且不调用 ...
- java 析构函数_C++虚函数
码字不易,欢迎给个赞! C++虚函数是多态性实现的重要方式,当某个虚函数通过指针或者引用调用时,编译器产生的代码直到运行时才能确定到底调用哪个版本的函数.被调用的函数是与绑定到指针或者引用上的对象的动 ...
- c++整理--虚函数
一.虚函数是这么实现的 解析: 简单的说,虚函数是通过虚函数表实现的,那么什么是虚函数表呢? 事实上,如果一个类中含有虚函数表,则系统会为这个类分配一个指针成员指向一张虚函数表(vtbl),表中每一项 ...
最新文章
- canvars 画花
- 「SAP技术」MIGO 343 解冻物料库存的同时可以更改存储地点
- csgo卡程序关不掉_微信推QQ小程序,取代QQ?网友:这功能有用?
- 成功解决TypeError: map() got an unexpected keyword argument 'num_threads'
- python删除长目录_python中删除目录名两端
- 一款基于jQuery底部带缩略图的焦点图
- 【Python】SNMP的安装及Python的调用
- 【CCCC】L3-011 直捣黄龙 (30分),Dijkstra维护点权,节点数,路径条数等+路径打印
- DIY远程控制开关(tiny6410+LED+yeelink+curl)
- jsp和servlet面试题
- 罗辑回归,Logistic Regression(or sigmoid function)
- 香港资深艺人沈殿霞病逝 享年60岁(图)
- 逆波兰式求值 —Java
- YS_20190822_图像_Matlab_04
- 前端(以Vue为例)webpack打包后dist文件包如何部署到django后台中
- linux钉钉-使用playonlinux 可以使用视频会议
- 统计学习方法-感知机概括和补充
- BugkuCTF~Misc~WriteUp
- 电子商务网站建设策划书范例
- 半年从转行软件测试到产品经理
热门文章
- access9磅字体是多_第一套考试题
- 树莓派udev不能自动挂载_直播课:教你用树莓派实现智能商店的自动结账
- linux ppp拨号 socket,请问GPRS模块ppp拨号不成功是什么原因
- jQuery实现王者手风琴案例
- 小忆《记录博客一周年》
- SAP Query达到select * where 的效果 2011-04-29
- supermap iobect .net 7.1.2 图例的拆分
- EXC_BAD_ACCESS错误
- 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATI
- MECARD格式的电子名片简单介绍