假设你有一套模拟股票处理的类层次结构,例如,购入流程,出售流程等。对这样的处理来说可以核查是非常重要的,所以随时会创建一个 Transaction 对象,将这个创建记录在核查日志中是一个适当的要求。下面是一个看起来似乎合理的解决问题的方法:
class Transaction { // base class for all
public: // transactions
Transaction();
virtual void logTransaction() const = 0; // make type-dependent
// log entry
...
};
Transaction::Transaction() // implementation of
{
// base class ctor
...
logTransaction(); // as final action, log this
} // transaction
class BuyTransaction: public Transaction {
// derived class
public:
virtual void logTransaction() const; // how to log trans-
// actions of this type
...
};
class SellTransaction: public Transaction {
// derived class
public:
virtual void logTransaction() const; // how to log trans-
// actions of this type
...
};
考虑执行这行代码时会发生什么:
BuyTransaction b;
同样的原因也适用于析构过程。一旦派生类析构函数运行,这个对象的派生类数据成员就被视为未定义的值,所以 C++ 就将它们视为不再存在。在进入基类析构函数时,对象就成为一个基类对象,C++ 的所有配件——虚函数,dynamic_casts 等——都如此看待它。
在构造函数和析构函数中调用虚函数的问题并不总是如此容易被察觉。如果 Transaction 有多个构造函数,每一个都必须完成一些相同的工作,好的软件工程为避免代码重复,会将共用的初始化代码,包括对 logTransaction 的调用,放入一个私有的非虚的初始化函数,叫做 init:
|
您将承担一切因您的行为、言论而直接或间接导致的民事或刑事法律责任
留言板管理人员有权保留或删除其管辖留言中的任意内容 本站提醒:不要进行人身攻击。谢谢配合。 |