1. 在构造和析构期间不要调用 virtual 函数,因为这类调用从不下降至 derived class(比起当前执行构造函数和析构函数的那层)。
class Transaction { // 所有交易的基类
public:
Transaction();
virtual void logTransaction() const = 0; // 记录日志
...
};
Transaction::Transaction()
{
...
logTransaction(); // 构造函数中最后一步是记录日志
}
class BuyTransaction: public Transaction { // 派生类
public:
virtual void logTransaction() const; // 记录日志
...
};
此时,若执行以下这行,会发生什么:
BuyTransaction b;
base class 构造期间 virtua l函数 的调用不会下降到 derived class 阶层!!!
原因: 由于 base class 构造函数的执行更早于 derived class 构造函数,当 base class 构造函数执行时 derived class 的成员变量尚未初始化。如果此期间调用的 virtual 函数下降至 derived classes 阶层,要知道 derived class 的函数几乎必然取用 local 成员变量,而那些成员变量尚未初始化。这可能导致不明确的行为。
根本原因: 在 derived class 对象的 base class 构造期间,对象的类型是 base class 而不是 derived class。不只 virtual 函数会被编译器解析至 base class,若使用运行期类型信息(例如 dynamic_cast(见条款27)和 typeid),也会把对象视为 base class 类型。对于析构函数也是相同的道理。
评论区