继承中,构造函数,赋值操作符,析构函数与虚函数的关系
2014-03-07 17:22
417 查看
为什么构造函数不能是虚函数呢?这里你需要知道一个概念,那就是虚函数表vtbl,每一个拥有虚成员函数的类都有一个指向虚函数表的指针。对象通过虚函数表里存储的虚函数地址来调用虚函数。那虚函数表指针是什么时候初始化的呢?当然是构造函数。当我们通过new来创建一个对象的时候,第一步是申请需要的内存,第二步就是调用构造函数。试想,如果构造函数是虚函数,那必然需要通过vtbl来找到虚构造函数的入口地址,显然,我们申请的内存还没有做任何初始化,不可能有vtbl的。因此,构造函数不能是虚函数。
赋值操作符设为虚函数可能会令人混淆,因为虚函数必须在基类和派生类中具有相同的形参。基类赋值操作符有一个形参是自身类类型的引用,如果该操作符为虚函数,则每个类都得到一个虚函数成员,该成员定义了参数为一个基类对象的operator=。但是对派生类而言,这个操作符是基类的行为,并不是派生类的行为,往往得出不同的结果。
基类中的析构函数必须为虚函数。试看基类Base和派生类ItemP的例子。 Base* base=new Itemp, 基类指针指向派生类类对象时,发生假切割。要知道这个过程只是切掉基类中没有的那些成员。当delete
base时,若析构函数没有定义为虚函数,则实际删除基类部分,而派生类部分的数据成员仍然存在内存中,从而造成内存泄漏。而定义为虚函数,则会根据动态对象调用适当的析构函数。
赋值操作符设为虚函数可能会令人混淆,因为虚函数必须在基类和派生类中具有相同的形参。基类赋值操作符有一个形参是自身类类型的引用,如果该操作符为虚函数,则每个类都得到一个虚函数成员,该成员定义了参数为一个基类对象的operator=。但是对派生类而言,这个操作符是基类的行为,并不是派生类的行为,往往得出不同的结果。
基类中的析构函数必须为虚函数。试看基类Base和派生类ItemP的例子。 Base* base=new Itemp, 基类指针指向派生类类对象时,发生假切割。要知道这个过程只是切掉基类中没有的那些成员。当delete
base时,若析构函数没有定义为虚函数,则实际删除基类部分,而派生类部分的数据成员仍然存在内存中,从而造成内存泄漏。而定义为虚函数,则会根据动态对象调用适当的析构函数。
相关文章推荐
- iOS 重力感应 学习1 陀螺仪 水平仪 指南针
- Google Chrome源码剖析【序】
- Flex String JSON 转换成 ArrayCollection
- 安装Eclipse反编译插件
- wait/sleep/yield的区别
- CramFS文件系统
- MFC类CRect、CPoint、CSize
- URITY_ATTRIBUTES 设置低权限
- UIApplicationDelegate协议定义的方法说明
- SQL自动补充其他月份为0
- XML文档的分类---2.1.2: 格式良好但无效的XML文档
- MySQL Migration Tool报“initialized java loader”错误的问题
- sqlserver数据导到mysql数据库的环境配置
- 菜鸟的IT道路ing (二)
- sql(1)
- 当心我们的葡萄
- sqlserver数据导到mysql数据库的环境配置
- Java运行JS库 -- Jsoup
- 用SNMP4J 写个SNMP模拟器
- 移动设备的界面设计尺寸