Effective C++——条款9(第2章)

条款09:    绝不在构造和析构过程中调用 virtual 函数

Never call virtual functions during construction or destruction

    不应该在构造函数和析构函数期间调用 virtual 函数,因为这样的调用不会带来预想的结果.

    假设有个 class 继承体系,用来模塑股市交易如买进,卖出的订单等等.这样的交易一定要经过审计,所以每当创建一个交易对象,在审计日志中也需要创建一笔适当记录.下面是一个看起来颇为合理的做法:
class Transaction {
public:
    Transaction();
    virtual void logTransaction() const = 0;
    ...
};
Transaction::Transaction() {
    logTransaction();
}
class BuyTransaction : public Transaction {
public:
    virtual void logTransaction() const;
};
class SellTransaction : public Transaction {
public:
    virtual void logTransaction() const;
};
    现在,当以下这行被执行,会发生什么事:
BuyTransaction b;
    无疑地有一个BuyTransaction构造函数被调用,但首先Transaction构造函数一定会更早地被调用.derived class 对象内的base class 成分会在derived class 自身成分在构造之前先构造,Transaction构造函数的最后一行调用 virtual 函数logTransaction,这正是引发惊奇的起点.这时候被调用的logTransaction是Transaction内的版本,不是BuyTransaction内的版本,即使目前即将建立的对象类型是BuyTransaction.base class 构造期间 virtual 函数绝不会下降到derived class 阶层.非正式的说话比较传神:在base class 构造期间,virtual 函数不是 virtual 函数.
     根本的原因是:在derived class 对象的base class 构造期间,对象的类型是base class 而不是derived class. 不只是 virtual 函数会被编译器解析至base class.若使用运行期类型信息(如 dynamic_cast 和 typeid)也会把对象视为base class 类型。对象在derived class 构造函数开始执行前不会成为一个derived class 对象.
    相同道理也适用于析构函数
.一旦derived class 析构函数开始执行,对象内derived class 成员变量便开始呈现未定义值,所以C++视它们仿佛不存在.进入base class 析构函数后对象就成为一个base class 对象,而C++的任何部分包括 virtual 函数,dynamic_cast 等等也那么看待它.
    一个好的做法就是:确定构造函数和析构函数都没有(在对象被创建和被销毁期间)调用 virtual 函数,而它们调用的所有函数都服从同一约束.
    注意:
    在构造和析构期间不要调用 virtual 函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值