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

不该在构造函数和析构函数期间调用virtual函数,这一点是C++与jave/C#不同的地方之一。

假设有一个class继承体系,用来模拟股市交易如买进、卖出的订单等等。这样的交易一定要经过审计,所以每当创建一个交易对象,在审计日志中也需要创建一笔适当记录。

正确的做法是在基类Transaction内将logTransaction函数改为non-virtual,然后要求派生类构造函数传递必要信息给基类Transaction的构造函数,这样那个构造函数便可安全地调用non-virtual logTransaction。正确用法如下:

class Transaction
{
public:
	Transaction();
	~Transaction();

	explicit Transaction(const string& logInfo);
	void logTransaction(const string& logInfo) const;	//non-virtual函数

private:

};

Transaction::Transaction(const string& logInfo)
{
	...
	logTransaction(logInfo);	//非non-virtual调用
}

 

class BuyTransaction : public Transaction
{
public:
	BuyTransaction(parameters) : Transaction(createlogString(parameters))	//将日志信息传递给基类构造函数
	{
		...
	}
	...
	~BuyTransaction();

private:
	static string createlogString(parameters);
};

  注意示例BuyTransaction内的private static函数 createlogString的运用。比起在成员初值列内给予基类所需的数据,利用辅助函数创建一个值传递给基类的构造函数往往比较方便(也比较可读)。令此函数为static,也就不可能意外指向“初期未成熟的BuyTransaction对象内尚未初始化的成员变量”。这很重要,正是因为“那些成员变量处于未定义状态”,所以在基类构造和析构期间调用的virtual函数不可下降至派生类。

请牢记:

 在构造和析构期间不要调用virtual函数,因为这类调用从不下降至派生类(比起当前执行构造函数和析构函数的那层)。

posted @ 2013-12-10 23:21  陌上归人  阅读(413)  评论(0编辑  收藏  举报