如下是一个股票交易的例子:

 1 class Transaction                               // 交易的基类
 2 {
 3 public:
 4     Transaction();
 5     virtual void logTransaction() const = 0;    // 用于记录交易日志
 6 };
 7 Transaction::Transaction()
 8 {
 9     logTransaction();              // 调用虚函数
10 }
11
12 class BuyTransaction : public Transaction       // 买进股票
13 {
14     virtual void logTransaction() const;
15 };
16 void BuyTransaction::logTransaction() const{ }
17
18 class SellTransaction : public Transaction      // 卖出股票
19 {
20     virtual void logTransaction() const;
21 };
22 void SellTransaction::logTransaction() const{ }
23
24 int main()
25 {
26 BuyTransaction b;
27
28 return 0;
29 }

上述代码中执行BuyTransaction b时,会调用基类的构造函数,而基类的构造函数会调用一个虚函数来完成工作。但是该虚函数是否会调用派生类的对应函数呢?答案是否定的,解释如下:

1>  基类的构造是先于派生类的构造的。当基类的构造函数执行时,派生类中的成员尚未被初始化,如果允许基类构造期间调用派生类的函数,可能也会调用了没有初始化的“垃圾值”,导致不确定行为发生。

2>  基类构造期间,virtual函数的行为绝对不会伸到派生类中,因为此时构造的是基类,即此时构造的对象的类型是基类而非派生类,这点很重要。

但是有时我们在构造基类的时候又需要派生类中才有的参数信息,如何解决:

在基类中将logTransaction函数改为非虚函数,然后在构造派生类时将必要的参数传递到基类的构造函数中去,像如下这样:

 1 #include <string>
 2
 3 class Transaction                                             // 交易的基类
 4 {
 5 public:
 6     explicit Transaction(const std::string& logInfo);
 7     void logTransaction(const std::string& logInfo) const;    // 用于记录交易日志
 8 };
 9 Transaction::Transaction(const std::string& logInfo)
10 {
11     logTransaction(logInfo);                  // 调用非虚函数12 }
13 void Transaction::logTransaction(const std::string& logInfo) const{ }
14
15 class BuyTransaction : public Transaction                     // 买进股票
16 {
17 public:
18     BuyTransaction(const std::string& parameter) : Transaction(parameter){ }
19 };
20
21
22 int main()
23 {
24     BuyTransaction b("BT");
25
26     return 0;
27 }

由上可知,如果基类构造时要使用派生类的信息,可以通过派生类构造函数的初始化列表传入相关参数,切不可调妄图调用虚函数实现,因为在构造基类期间其对象的类型是基类类型。

对于析构函数也是同样的道理,基类的析构总是在派生类析构后才进行,此时派生类的对象已经不存在了,而调用虚函数必然会引发一个不确定行为。当然你也可以将基类的虚函数实现后在析构函数中进行调用,但是这样的话,为什么不定义为非虚函数呢,虚函数的意义将不复存在了。

转载于:https://www.cnblogs.com/benxintuzi/p/4527948.html

条款9:不要在构造和析构过程中调用virtual函数相关推荐

  1. Effective C++条款09:绝不在构造和析构过程中调用virtual函数

    Effective C++条款09:绝不在构造和析构过程中调用virtual函数(Never call virtual functions during construction or destruc ...

  2. C++绝不在构造和析构过程中调用virtual函数

    绝不在构造和析构过程中调用virtual函数 如果希望在继承体系中根据类型在构建对象时表现出不同行为,可以会想到在基类的构造函数中调用一个虚函数: class Transaction { //所有交易 ...

  3. 关于构造与析构过程中调用虚函数的问题

    今天面试碰到一个构造函数与析构函数中调用需虚函数的问题,当时不太确定,回来敲了一下,发现确实表现的不一样,在网上一查发现另有玄机. 代码: # gcc version 4.8.2 (Ubuntu 4. ...

  4. 绝不要在构造函数和析构过程中调用virtual函数

    下面是一个用来塑模股市交易的类: derived的类的构造函数被调用,但是首先得调用基类Transaction的构造函数,但是在后面还得调用virrual函数,这个时候子类的对象的构造还没有完成,那么 ...

  5. 开机启动加载驱动过程中调用PostMessage函数出错

    今天在WINCE5.0+S3C2440系统调试检测出租车是否载客的驱动的时候遇到这样的问题: 发现在开机启动加载驱动过程中调用PostMessage函数时会导致调用的线程崩溃,比如如果下面的线程在创建 ...

  6. OpenCV 相机校正过程中,calibrateCamera函数projectPoints函数的重投影误差的分析

    OpenCV 校正过程中,calibrateCamera函数的ret和重投影误差的分析 OpenCV对相机进行校正的过程中,校正返回值retval和重投影误差的计算公式表示和分析. OpenCV 校正 ...

  7. 只能在执行 Render() 的过程中调用 RegisterForEventValidation

    当用GridView导出Execl的时候,会发生只能在执行 Render() 的过程中调用 RegisterForEventValidation的错误提示.有两种方法可以解决以上问题: 1.修改web ...

  8. 异常“只能在执行Render()的过程中调用RegisterForEventValidation”的解决办法(转)...

    当出现下面的异常的时候: 只能在执行Render()的过程中调用RegisterForEventValidation 当出现的异常的提示: 异常详细信息: System.InvalidOperatio ...

  9. 不要在构造和析构函数中调用虚函数

    构造函数中不能有虚函数的原因: 原因一:基类构造期间虚函数不会下降到派生类阶段,也就是本身我们声明一个派生类对象,它应该先去调用基类的构造,若此时基类构造里面有虚函数,则这个虚函数是基类的虚函数,而不 ...

最新文章

  1. 【转】用例结构优化心得
  2. 上传文件大小限制,webconfig和IIS配置大文件上传
  3. Android之稍微靠谱点的透明Activity(不获取触摸事件)
  4. 论文浅尝 | 基于深度强化学习的远程监督数据集的降噪
  5. 语言做一个自动售货机软件_软件开发手机app系统软件高端定制做一个app软件要多少钱...
  6. 解决Numpy 报错 ValueError: zero-size array to reduction operation maximum which has no identity
  7. Java注解之自定义注解
  8. 世界各国简称 电话区号JSON数据
  9. 云计算平台的市场现状和云计算平台的核心价值是什么?
  10. 华为快应用-怎么使用卡片功能
  11. SaaSpace:最好的免费网络安全工具
  12. lisp方格网法计算土方量_CAD计算土方方量插件
  13. python画一个心形照片墙怎么摆_这个七夕节,用Python为女友绘制一张爱心照片墙吧!...
  14. 韩寒诉百度文库侵权案分析
  15. STC12C5A60S2输出时钟频率
  16. 2012人类将从“微博体”过渡到“微媒体”。至于你信不信,反正我信了
  17. selenium自动化测试--126邮箱登录问题总结
  18. 毫米波电路的PCB设计和加工(第一部分)
  19. 计算机网络与技术课本,高等学校计算机科学与技术教材:计算机网络基础教程...
  20. 网龙前员工:解读百度收购91无线的内幕

热门文章

  1. 计算机网络解决数据包丢失,数据包丢失时网络控制系统的稳定性分析及设计
  2. PSAM卡---中国人民银行PSAM卡管理规范.doc
  3. Content-Type一览
  4. linux火狐浏览器49.0安装教程,firefox for linux
  5. 微信小程序 没有找到可以构建的npm包
  6. 单链表反转的原理和python代码实现
  7. loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】
  8. 多个工作表同时处理+选中不连续的单元格和工作表
  9. 【MySQL】玩转定时器
  10. POJ 2785 4 Values whose Sum is 0