首页 > 代码库 > 深度探索C++对象模型-----编译器’何时‘自动合成nontrivial default constructor

深度探索C++对象模型-----编译器’何时‘自动合成nontrivial default constructor

有4种情况,会造成“编译器必须为 未申明constructor的classes合成default constructor。

1.带有default constructor的member class object

如果一个class没有任何constructor,但是内含一个member object ,而后者有default constructor,那么这个class的implicit default constructor就是 nontrivial,编译器需要为改class合成出一个default constructor。不过这个合成只有在constructor真正需要被调用时才发生。

程序片段:

class Foo{
         public:
              Foo();
              Foo(int);
           .........
};
class Bar{
         public:
             Foo foo;
             char *str;
          ......
};
void foo_bar()
{
     Bar bar;//Bar::foo必须在此处初始化
                 //Bar::foo是一个member object,而其class Foo拥有default constructor
     if(str)
             .....
}

被合成的Bar default constructor内含必要的代码,能够调用class Foo的default constructor来处理member object Bar::foo,但它并不产生任何代码来初始化Bar::str,将Bar::foo初始化是编译器的责任,将Bar::str初始化是程序员的责任。

如果程序员定义如下代码片段:

Bar::Bar(){str = 0;}

编译器的行动将会是:将class Bar中内含的Bar::foo调用foo的default constructor。编译器会将这些操作放在user code之前执行。扩张后的代码如下:

Bar::Bar(){
		foo.Foo::Foo();//编译器安插代码,根据member object的申明顺序初始化
		str = 0;//user code
	}
2.带有default constructor的Base class

类似的道理,如果一个没有任何constructor的class 派生自一个带有default constructor的base class,那么这个derived class的default constructor会被视为nontrivial,并因此被合并出来。

如果设计者提供了多个constructors,但其中没有default constructor,编译器会扩张现存的每一个constructor,将用以调用所有必要之default constructor的程序代码加进去。它不会合成一个新的default constructor,因为其他由user所提供constructor存在的缘故。

如果存在default constructor的member class object,那么这些member的default也会被调用,在所有的base class constructor调用之后。

另外两种情况:

3.class 申明(继承)一个virtual function

4.class 派生自一个继承串链,其中有一个或更多的virtual base class。


总结:

以上四种情况,编译器必须为未申明constructor的class 合成一个default constructor。C++ Standard把这些合成物称为implicit nontrivial default constructor,被合成的constructor只能满足编译器的需要。

至于没有这四种情况而又没有申明任何constructor的class,我们说它们拥有的是implicit trivial default constructor,它们实际上并不会被合成出来。

在合成的default constructor中,只有base class subobject和member class object会被初始化,所有其他的nonstatic data member(如整数,整数指针,整数数组等)都不会被初始化。这些初始化都需要程序员操作。

C++新手一般有两个常见的误解

1.任何class如果没有定义default constructor,就会被合成一个

2.编译器合成出来的default constructor会显式设定class 内每一个class member的默认值。


深度探索C++对象模型-----编译器’何时‘自动合成nontrivial default constructor