首页 > 代码库 > 编译器在构造函数里都做了些什么?

编译器在构造函数里都做了些什么?

  我们都知道,C++是一种面向对象的语言,其中一个重要特性是多态性。多态性是通过基类指针指向子类对象,并通过这个基类指针调用子类函数(虚函数)来实现的。但是,看下面这个例子,我可以通过在构造函数里增加一行代码,从而使得这个多态不起作用!

  看下面例子:

class Base{public:    Base()    {        cout<<"Base::Base()"<<endl;    }    virtual ~Base()    {        cout<<"Base::~Base()"<<endl;    }    virtual void print()    {        cout<<"Base::print()"<<endl;    }};class Derived: public Base{public:    Derived()    {        //memcpy(this, 0, sizeof(Derived));        cout<<"Derived::Derived()"<<endl;        memset(this, 0, sizeof(Derived));    }    ~Derived()    {        cout<<"Derived::~Derived()"<<endl;    }    void print()    {        cout<<"Derived::print()"<<endl;    }};int main(){    Base *b = new Derived();    b->print();    return 0;}

  如果按照C++的多态特性,它应该输出:Derived::print(),但是真是如此吗?

  下面,我们编译,运行,看看输出什么东西:

$ ./nopoly Base::Base()Derived::Derived()Segmentation fault (core dumped)

  令人大跌眼镜,居然段错误!什么也没能输出,是什么原因导致的呢?其实是因为这么一行代码:

memset(this, 0, sizeof(Derived));

  我们将vpt清为零了,因此,找不到Deried类的print函数,因此,便出现段错误了。

 

  那么,我们回想一下,编译器到底在我们的构造函数里都干了些什么。

1. 记录在 member initialization list 中的 data members 初始化操作会被放进构造函数本身,并以members声明的顺序进行初始化;

2. 如果有一个member并没有出现在member initialization list 中,但它有一个default constructor,那么,该default constructor 必须被调用;

3. 在那之前,如果class object有virtual table pointer(s),它(们)必须被设定初值,并指向适当的virtual table(s)。

4. 在那之前,所有上一层的 base class constructors 必须被调用,并以base class 的声明顺序为次序(与member initialization list 中的顺序没有关联):

  如果base class 被列于member initialization list中,那么任何明确指定的参数都应该传递过去;

  如果base class 没有被列于 member initialization list 中,而它有default constructor (或default memberwise copy constructor ),那么就调用之。

  如果base class 是多重继承下的第二或后继的base class ,那么this 指针必须有所调整。

5. 在那之前,所有 virtual base class constructors 必须被调用,从左到右,从最深到最浅:

  如果class 被列于member initialization list 中,那么如果有任何明确指定的参数,都应该传递过去。若没有列于list 中,而class 有一个default constructor,也应该调用之。

  此外,class 中的每一个virtual base class subobejct 的偏移量必须在执行期可被存取;

  如果class object 是最底层的 class,其constructors 可能被调用;某些用以支持这个行为的机制必须被放进来。

 

编译器在构造函数里都做了些什么?