条款9:绝不要在构造以及析构函数中调用虚函数
在构造以及析构函数期间不要调用virtual函数,因为这类调用从不下降到derived class中。例如说下面这个例子:
1 class Transaction{ 2 public: 3 Transaction(); 4 virtual void logTransactions()s const = 0; 5 //... 6 }; 7 Transaction::Transaction() 8 { 9 //... 10 logTransaction(); 11 } 12 class BuyTransaction : public Transaction{ 13 public: 14 virtual void logTransaction() const; 15 ... 16 }; 17 class SellTransaction : public Transaction{ 18 public: 19 virtual void logTransaction() const; 20 ... 21 };
比如构造函数中调用了一个虚函数,其derived class在构造的过程中我们的本意是让derived class调用derived class自己的虚函数版本。但是事实上,由于这个时候derived class还没有构造完成,所以这个时候这里调用的将会是base class的虚函数版本。这是不可以让人接受的
应对上面这个例子来说,就是在Buytransaction构造期间,会先行构造基类,但是调用logTransaction的时候调用的会是基类的版本而不是派生类的版本,这个当然不能让人接受。
所以说在base class构造期间,虚函数还不是虚函数。
同样的事也会发生在析构函数的身上,一旦derived class的析构函数开始执行的话,对象内的derived class成员变量便出现未定义值,这时c++便将他们是视为不存在了。一旦进入base class析构函数之后对象就成了一个base class对象。
所以由于我们无法使用virtual函数从base class向下调用,在构造器件,可以由“令derived classes将必要的构造信息向上传递至base class构造函数”来加以弥补