条款09:绝不在析构和构造过程中调用virtual函数

来源:互联网 发布:淘宝卖家手机怎么登录 编辑:程序博客网 时间:2024/05/03 13:51

确定你的构造函数和析构函数都没有调用virtual函数,而它们调用的所有函数也都服从同一约束。

如下程序:

#include "stdio.h"class Base{public:    Base()    {        Init();    }    virtual void Init()    {        printf("Base Init\n");    }    void func()    {        printf("Base func\n");    }};class Derived: public Base{public:    virtual void Init()    {        printf("Derived Init\n");    }    void func()    {        printf("Derived func\n");    }};int main(){    Derived d;    ((Base *)&d)->func();    return 0;}

该程序的执行结果
A.Base Init,Derived func
B.Base Init ,Base func
C.Derived Init,Base func
D.Derived Init,Derived func
答案是B

  Derived class对象内的base class成分会在derived class自身成分被构造之前先构造妥当。Base class构造期间virtual函数绝不会下降到derived classes阶层。取而代之的是,对象的作为就像隶属于base类型一样。非正式的说法或许比较传神:在base class构造期间,virtual函数不是virtual函数。

  • 由于base class构造函数的执行更早于derived class的构造函数,当base class的构造函数执行时,derived class的成员变量尚未初始化。如果此期间调用的virtual函数下降至derived class阶层,要知道derivedlass的函数几乎必然会取用local成员变量,而它们尚未初始化。   
  • 在derived class对象的base class构造期间,对象的类型是base class而不是derived class。不只virtual函数会被编译器解析至base class,若使用运行期类型信息,也会把对象视为base class类型。对象在derived class构造函数开始前不会成为一个derived class对象。

    相同的道理也适用于析构函数。一旦derived class析构函数开始执行,对象内的derived class成员变量便呈现未定义值,所以C++视它们仿佛不再存在。进入base class析构函数后,对象就成为一个base class对象,而C++的任何部分包括virtual函数、dynamics_casts等等也就那么看待它。

0 0
原创粉丝点击