深入探索C++对象模型:Default Constructor的构造操作

那么,什么时候才会合成出一个default constructor呢?——当编译器需要它的时候!此外,被合成出来的constructor只执行编译器所需的行动。

[x]“任何class如果没有定义default constructors,就会被合成出一个来”?——

[x]“编译器合成出来的default constructors会显式设定class内每一个data member默认值”?——

以下分别讨论了编译器会主动合成出default constructor的四种情况。

1.“带有Default Constructor”的Member Class Object

举个例子:Bar类没有任何构造函数,但它内含一个成员对象,而Foo类有默认构造函数,此时编译器需要为Bar类合成出一个构造函数。(大概这个样子…)

class Foo {//explict constructor
public:
Foo(){}
};
class Bar {//no default constructor
public:
Foo foo; //member object
char* str;
};

编译器为什么要为Bar类合成构造函数?(答:因为要构造Foo类)。

Bar类“无”构造函数时

那么,编译器合成的构造函数大概是什么样子呢?(答:伪代码如下)。

Bar::Bar(){
foo.Foo::Foo();
}

Bar类“有”构造函数时

如果,有构造函数,那么编译器就会扩张(改写)已有的构造函数。编译器附加上的代码会在用户自定义的代码之前(大概是这个样子…)explicit user code表示是用户自定义的代码部分。

Bar::Bar(){
foo.Foo::Foo(); //compiler code
//...explicit user code
}

另外,还有点需要注意的:“如果Bar类中有多个类似于Foo类这样的成员对象,那么编译器扩张(或者生成)构造函数的时候,会按照成员对象的声明顺序,生成foo.Foo::Foo()类似的代码”。

2.“带有Default Constructor”的Base Class

举个例子:基类Foo含有默认的构造函数,而子类Bar却没有声明构造函数,此时编译器会为Bar类合成一个构造函数。为什么会被合成?(答:因为要调用基类的构造函数,并初始化基类)

class Foo {//explict constructor
public:
Foo(){}
};
class Bar : public Foo {
public:
char* str;
};

注意:一直说的是带有默认构造函数(就是显示声明了一个不需要任何参数的构造函数,或者全部有默认参数的构造函数),这点儿要注意。否则的话必须显示指定构造函数,而不能由编译器合成。

3.“带有一个Virtual Function”的Class

举个例子:(如下)class声明(或继承)一个virtual function。这种情况下,编译器为什么要合成构造函数?答案…..在见下文。

class Foo {
public:
virtual void foo() = 0;
};
class Bar : public Foo {
public:
char* str;
};

答:因为编译器需要…一些信息,所以需要合成构造函数。那么,需要什么呢?

其一,编译器会构造一个virtual function table,里面存放类的virtual function地址。
其二,编译器会在每一个类中增加一个vptr指针(它用来指向上面的虚函数表….)。

4.“带有Virtual Base Class”的Class

举个例子:(如下)必须使得虚基类在子类中的位置,能够在执行期间确定。那么,编译器需要做什么?这个等以后再补充。。。

class Foo {
};
class Foo1 : virtual public Foo {
//__vbcFoo
};
class Foo2 : virtual public Foo {
};
class Bar : public Foo1, public Foo2 {
};

Reference:
《深度探索C++对象模型》 侯捷 译