-
在基类中构造函数中调用virtual函数带来不安全
#include <iostream> class Transaction { public: Transaction() { logTransaction(); } virtual void logTransaction() const = 0; }; class BuyTransaction : public Transaction { public: virtual void logTransaction() const{ printf("BuyTransaction \n"); }; }; class SellTransaction : public Transaction { public: virtual void logTransaction() const{ printf("SellTransaction \n"); }; }; int main() { SellTransaction *bb = new SellTransaction; //先调用Transaction构造函数,在调用SellTransaction构造函数 return 0; }
class Transaction的构造函数调用logTransaction()是有问题的,编译都不会通过。因为Transaction构造函数调用的是自己的virtual函数,main中SellTransaction *bb = new SellTransaction;的操作的流程是:调用SellTransaction的构造函数--->调用Transaction的构造函数。但在构造函数期间,基类与派生类并没有发生virtual的动态绑定,Transaction调用不到SellTransaction的logTransaction函数。简单的说:类构造函数中的virtual函数,不带virtual的性质,就是个普通函数。
- 为何基类的构造函数不能调用派生类的virtual函数呢?
(1)如果调用基类构造函数,这个时候可以调用派生类的virtual函数(也就是virtual函数绑定好了),那如果派生类的变量未初始化,那么这个派生类的virtual函数的调用将为程序带来不确定性,完全就是引入风险的操作,所以基类构造函数期间virtual函数不是virtual函数。
(2)同理适用于析构函数,当Derived类析构,Base类再析构,Base类的析构函数就不该能调用virtual函数,因为这个时候Derived类已经使用结束了,它的成员函数,变量再使用也是不安全的,所以Derived类析构之后,Base类的析构函数不应该有virtual的使用,
- 如何在有Derived类对象被构造时,调用正确的Base类函数呢?
- 通过Derived类向Base类传递参数来调用Base类的构造函数,说白了,就是在Base类写歌函数,不要用virtual
class Transaction { public: explicit Transaction(const std::string& logInfo) { logTransaction(logInfo) } void logTransaction(const std::string& logInfo) const; // non-virtual }; class BuyTransaction : public Transaction { public: BuyTransaction(parameters): Transaction(createLogString(parameters)) {} private: static std::string createLogString(parameters); }; class SellTransaction : public Transaction { public: SellTransaction(parameters): Transaction(createLogString(parameters)) {} private: static std::string createLogString(parameters); };
- 总结:不要再构造,析构函数调用virtual函数。