第2个回答 推荐于2016-01-24
根据Effective C++ (3rd Edition) ---- Item 9:
Never call virtual functions during construction or destruction.
(不要在构造函数和析构函数中调用虚函数)
其中举例为:(英文)
class Transaction {
public:
Transaction();
virtual void LogTransaction() const = 0;
// ...
};
Transaction::Transaction()
{
// ...
LogTransaction();
}
class BuyTransaction : public Transaction {
public:
virtual void LogTransaction() const;
// ...
};
Consider what happen when this code is executed:
BuyTransaction b;
Clearly a BuyTransaction constructor will be called, but firt, a Transaction constructor must be called; base class parts of derived class objects are constructed before derived class parts are. The last line of the Transaction constructor calls the virtual function longTransaction, but this is where the surprise comes in. The version of logTransaction that't called is the one in Transaction, not the one in BuyTransaction -- even though the type of object being created is BuyTransaction. During base class construction, virtual functions never go down into derived classes. Instead, the object behaves as if it were of the base type. Informally speaking, during base class construction, virtual functions aren't.
There's a good reason for this seemingly counterintuitive behavior. Because base class constructors execute before derived class constructors, derived class data members have not been initialized when base class constructors run. If virtual functions called during base class construction went down to derived classes, the derived class functions would almost certainly refer to local data members, but those data members would not yet have been initialized. That would be a non-stop ticket to undefined behavior and late-night debugging sessions. Calling down to parts of an object that have not yet been initialized is inherently dangerous. so C++ gives you no way to do it.
根据上面的原文看:调用的结果是(可能发生未定义行为)
这是由于(上例中)在BuyTransaction构造函数执行时,先执行基类(Transaction)的构造函数,而在Transaction的构造函数中又调用了(纯)虚函数logTransaction(),由于现在是在派生类里边定义函数,所以调用的logTransaction是BuyTransaction()里边的函数。这样有违背了你的初衷(调用Transaction里边的logTransaction())...
如果在虚函数里边有对派生类成员(不是从基类那里继承来的)的操作,那么更遭,以为在调用基类构造函数调时(派生类的成员还没有被初始化),这样就会导致未定义行为。
你最好看看原文的解释(英文部分)!
总之,记住不要在构造函数(析构函数)中调用虚函数!本回答被提问者采纳