zoukankan      html  css  js  c++  java
  • C++ 笔记(二) —— 不要在构造和析构函数中调用虚函数

    ilocker:关注 Android 安全(新手) QQ: 2597294287

     1 class Transaction { //所有交易的 base class
     2 public:
     3     Transaction();
     4     virtual void logTransaction() const = 0; //做出一份因类型不同而不同的日志记录
     5  6 }
     7 Transaction::Transaction() {
     8  9     logTransaction();
    10 }

    derived class:

     1 class BuyTransaction : public Transaction {
     2 public:
     3     virtual void logTransaction() const;
     4  5 }
     6 class SellTransaction : public Transaction {
     7 public:
     8     virtual void logTransaction() const;
     9 10 }

    现在执行:

    1 BuyTransaction b;

    derived class 对象内的 base class 部分首先构造,所以 Transaction 构造函数先被调用。在 Transaction 构造函数中调用的 logTransaction 是 Transaction 的版本,而不是 BuyTransaction 的版本,即使创建的对象类型是 BuyTransaction。

    base class 构造期间,virtual 函数绝不会下降到 drived classes 阶层,因为此时 drived class 的成员变量尚未初始化,如果 virtual 函数访问了未初始化的成员变量,就会导致不明确行为,c++ 不允许这种危险操作。

    更明确的说:在derived class 对象的 base class 构造期间,对象的类型就是 base class,而不是 derived class,这一点对 RTTI (如 dynamic_cast、typeid) 同样有效。

    同样的道理,在执行 base class 的析构函数时,derived class 的析构函数已执行完毕,derived class 的成员变量呈现未定义值,c++ 视他们不存在,此时对象就是一个 base class 对象。

    在示例中,构造函数直接调用了 virtual 函数,此外还应注意构造函数和析构函数有没有间接调用 virtual 函数。

    学习资料: 《Effective C++》

  • 相关阅读:
    全面提价2499元起小米6发布:四曲陶瓷机身+骁龙835+变焦双摄(小米在设计上也多次获得红点最佳、iF金奖等72项工业设计大奖)
    VCL的通用属性,方法和事件 good
    抗日名将粟裕
    部署 Redis 群集
    Xamarin
    NET Core控制反转(IoC)
    C#开发Linux守护进程
    数据一致性(consistency)、服务可用性(availability)、分区容错性(partition-tolerance)
    ssm框架
    javascript面向对象之闭包
  • 原文地址:https://www.cnblogs.com/ilocker/p/4782807.html
Copyright © 2011-2022 走看看