码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-08-28 11:06:21      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

条款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(比起当前执行构造函数和析构函数的那层).

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:

原文地址:http://blog.csdn.net/yiranant/article/details/48048523

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!