能不能在构造函数和析构函数中调用虚函数?
2016-04-16 10:52
477 查看
可以,但是达不到想要的效果,应该尽可能避免在构造函数和析构函数中调用虚函数。
当定义一个derived实例对象时,在base的构造函数中调用size()会被静态的决议为base::size()而不是derived::size()。
可以这么理解,当在构造base部分时,derived并不一个完整的实例对象,derived部分的成员变量甚至没有被初始化,如果在构造base期间调用的是derived的虚函数并且该虚函数引用了尚未构造好的成员变量,试想会发生什么。所以,从安全性考虑,经由构造中的对象来调用一个虚函数,其函数就是正在构造的对象的所属函数。
同时析构函数也如此。当正在析构base部分时,derived部分已经被析构完毕,成员变量已经无效,调用的虚函数是所属base的。
下面解释一下编译器是怎么做到的?
虚函数调用和实例对象的虚指针以及类的虚表有关。因此想要控制虚函数的调用,就必须控制虚指针的初始化。所以当一个实例对象正在构造base部分时,此时该实例的虚指针必须指向base类的虚表。那么虚指针何时被初始化,在程序员编写的代码之前或者是构造函数中初始化成员列表中所列的成员初始化操作之前。
class base{ public: base(){ cout<<The size is size()<<endl; } private: virtual size_t size(){ return sizeof(*this); } }; class derived : public class base{ public: derived(){ cout<<The size of is size()<<endl; } private: size_t size(){ return sizeof(*this); } };
当定义一个derived实例对象时,在base的构造函数中调用size()会被静态的决议为base::size()而不是derived::size()。
可以这么理解,当在构造base部分时,derived并不一个完整的实例对象,derived部分的成员变量甚至没有被初始化,如果在构造base期间调用的是derived的虚函数并且该虚函数引用了尚未构造好的成员变量,试想会发生什么。所以,从安全性考虑,经由构造中的对象来调用一个虚函数,其函数就是正在构造的对象的所属函数。
同时析构函数也如此。当正在析构base部分时,derived部分已经被析构完毕,成员变量已经无效,调用的虚函数是所属base的。
下面解释一下编译器是怎么做到的?
虚函数调用和实例对象的虚指针以及类的虚表有关。因此想要控制虚函数的调用,就必须控制虚指针的初始化。所以当一个实例对象正在构造base部分时,此时该实例的虚指针必须指向base类的虚表。那么虚指针何时被初始化,在程序员编写的代码之前或者是构造函数中初始化成员列表中所列的成员初始化操作之前。
相关文章推荐
- 从一次谷歌面试趣事中想到问题的更好的解决办法
- 《Linux内核设计与实现》第四章读书笔记
- ssh配置文件说明
- MIRO校验过程
- 『 Spark 』1. spark 简介
- 工厂模式
- 使用Zabbix中遇到的问题:snmp监控端口流量偶尔会断图
- 数组读书笔记
- 字符常量内存分配
- silhouette value 聚类
- adb操作命令详解及大全
- 《Java程序设计基础》 第8章手记Part 2
- (转)海明校验码--确定校验位
- JAVA I/O系统
- 频繁项挖掘算法Apriori和FGrowth
- 实验八 进程的切换和系统的一般执行过程
- fisher criterion
- 为什么要来CSDN
- Mysql select语句设置默认值
- 深度学习框架的评估与比较