c++标准中 默认构造函数在没有任何user-declared constructor的下,编译器会隐式地声明出来,而合成出来的default constructor 是没啥子用。default constructor 只是满足编译器的需要,而不是程序员的需要,所以并满足程序员的要求。什么时候会合成一个nontrivial default constructor(指的是编译器需要的) 为以下四种情况;
一、带有default constructor 的member Class Object
如果一个class没有任何constructor,但是内含一个member object,且其有default constructor,则该class的default constructor 就是nontrivial.但是这个合成的操作在constructor真正的被调用的时候才会发生。对于多个源文件内的合成操作,编译器以inline的方式合成,因为inline函数有static linkage,不会被当前文件以外者所看到。
class Foo
{
public:Foo();
Foo(int)...
}
class Bar{
public:
Foo foo;
char *str;
}
</pre><pre name="code" class="cpp">void foo_bar()
{
Bar bar;//这里将要合成
if(str){...}
}
<span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="cpp">inline Bar::Bar()
{
foo.Foo::Foo();
}
上述代码中,编译器合成的default constructor 只负责初始化bar中的foo部分,而str成员的初始化时程序员的责任。
定义defautlt constructor为:
Bar::Bar()
{
str=0;
}
但是由于user-defined constructor存在,编译器不会合成操作。对于foo部分的初始化,编译器会在上面的constructor中安插一些代码,在user code 执行之前,调用需要的default constrcutor.
Bar::Bar()
{
foo.Foo::Foo();
str=0;
}
如果内含多个class member object 时,将按照在class的声明顺序,逐个调用每个member object的default constructor
class Dopey{
public:
Dopey();
}
class Sneezy()
{
public:
Sneezy(int);
Sneezy();
}
class Bashful()
{
public:
Bashful();
}
class Snow_White{
public:
Dopey dopey;
Sneezy sneezy;
Bashful bashful;
private:
<span style="white-space:pre"> </span>int mutable;
}
</pre><pre name="code" class="cpp">Snow_White::Snow_White():sneezy(1024)
{
<span style="white-space:pre"> </span>mutable=2048;
}
上面的代码,编译器安插代码之后,像这样:
Snow_White::Snow_White():sneezy(1024)
{
<span style="white-space:pre"> </span>dopey.Dopey::Dopey();
<span style="white-space:pre"> </span>sneezy.Sneezy::Sneezy();
<span style="white-space:pre"> </span>bashful.Bashful::Bashful();
<span style="white-space:pre"> </span>mutable=2048;
}
二、带有default constructor 的base class
派生类的default constructor 是nontrivial的。
三、带有 virtual function 的class
合成default constructor在编译期间执行两个步骤:
a、virtual function table 由编译器产生,内含每个class的virtual funciton 的地址;
b、每个class object 内,额外的vptr由编译器产生,内含virtual function table的地址。
四、带有virtual base class的class
小结:以上四种情况造成编译器必须为未声明的constructor的classes合成一个default constructor。在c++标准中成为implicit nontrivial default constructor。合成出来的函数只是满足编译器的需要。只有base class subobject 和member class objects 才被初始化,其他的nonstatic data member(如整数、整数数组,整数指针),由程序员负责其初始化。两个常见的误解:1)、任何class 如果没有定义default constructor ,编译器会为我们合成一个;
2)、编译器合成的default constructor会显示的设定class内的每个data members的默认值。