编写代码时,不应该在构造/析构函数中调用virtual函数,因为这样做不会给你预想的结果!例如我们有以下几个类:
-
class Transaction {
-
public:
-
Transaction();
-
virtual void logTransaction() const = 0; //log different obj operations
-
//...
-
};
-
-
Transaction::Transaction()
-
{
-
//...
-
logTransaction();
-
}
-
-
class BuyTransaction: public Transaction {
-
public:
-
virtual void logTransaction() const;
-
//...
-
};
-
-
BuyTransaction bt;
基类Transaction构造函数内虚函数的用意在于,每当被不同类继承时,依照不同类特性对交易操作进行log记录。
然而,
当我们创建一个BuyTransaction 对象时,基类Transaction对象先被创建,此时继承类BuyTransaction对象还没有被创建,一切有关继承类的成员都还未定义,虚函数logTransaction实际上是基类Transaction的成员(C++编译器不会将virtual指针指定为还不存在的函数),而并非BuyTransaction的成员。
同样的道理也适用于析构函数。
既然在构造函数中不能调用虚函数来实现适用于不同类版本的logTransaction函数,那么该如何实现?
通常有一种做法是,
在Transaction类内将logTransaction实现为non-virtual函数,然后要求derived-class构造函数传递必要信息给Transaction构造函数。
而后那个构造函数便可安全地调用non-virtual logTransaction函数。
比如:
-
class Transaction {
-
public:
-
explicit Transaction(const std::string &logInfo);
-
void logTransaction(const std::string &logInfo) const;
-
//...
-
};
-
-
Transaction::Transaction(const std::string & logInfo)
-
{
-
//...
-
logTransaction(logInfo);
-
}
-
-
class BuyTransaction: public Transaction {
-
public:
-
BuyTransaction(parameters): Transaction(createLogString(parameters))
-
{
-
//...
-
}
-
//...
-
-
private:
-
static std::string createLogString(parameters);
-
};
换句话说,由于你无法使用virtual函数从base class向下调用,
在构造期间,你可以藉由“另derived class将必要的信息传递给base class的构造函数”替换加以弥补之。
同时,这里需要注意private 里面static函数createLogString的应用。
令此函数为static,也就不可能意外指向“初期BuyTransaction对象内尚未初始化的成员变量”。
阅读(1293) | 评论(0) | 转发(0) |