您的位置:首页 > 编程语言 > C语言/C++

[深度探索C++对象模型] 默认构造函数和拷贝构造函数的构造操作

2014-03-03 22:34 351 查看
默认构造函数和拷贝构造函数是C++中的一个重要内容,知道编译器会合成它对编程是很有用的。

首先,什么是默认构造函数?有人说是由编译器合成的构造函数,还有人说是无需参数的构造函数,两种说法都是不正确的。默认构造函数就是调用时无需提供参数的构造函数,因此,它可以是没有参数的,也可以是所有参数都有默认值,当然,两种情况只能采用一种,不然的话,就会产生二义性。

那么:

(1)何时编译器会合成一个默认构造函数?

(2)默认构造函数做什么?

这里需要引入一个词:trivial,意思是无用的。当默认构造函数实际上并没有干什么事时,就称它是trivial,在这种情况下,默认构造函数并没有被合成。因此,只有当编译器认为默认构造函数要干一些有用的事时,它才会合成默认构造函数。而且,这通常都和类成员或者虚函数机制相关,因为要调用其它类的默认构造函数或者做一些虚拟机制的准备工作。

1 当类中的类成员有默认构造函数时

如果类A中含有类成员b,类成员b有默认构造函数,而类A没有定义构造函数,那么,在构造A的对象时默认构造函数就需要调用b的默认构造函数,此时,就会合成默认构造函数,调用b的默认构造函数类构造A的对象。需要注意的是,A的合成的默认构造函数只会调用类成员的默认构造函数,不会初始化其它基本数据类型或者字符串。

如果类A中含有类成员b,类成员b有默认构造函数,而类A定义了构造函数却没有定义默认构造函数,那么,编译器会扩充A的每一个构造函数,先调用b的默认构造函数,然后调用A的构造函数。

对于上面两种情况,如果是多个类成员,就以类成员在类中的声明顺序来调用默认构造函数。

2 当基类有默认构造函数时

如果基类有默认构造函数,派生类没有构造函数,那么,在构造派生类对象时,默认构造函数需要调用基类的默认构造函数,因此,派生类的默认构造函数是trivial,这种情况下,需要合成默认构造函数。

同上面类似,如果基类有默认构造函数,派生类定义了构造函数却没有定义默认构造函数,那么,编译器会扩充派生类的每一个构造函数,先调用基类的默认构造函数,然后调用派生类的构造函数。

3 当类中有虚函数或者类派生链中有虚函数时

当类中有虚函数或者类派生链中有虚函数,在生成对象时,编译器会为每个派生类设置虚函数表的地址,它们的默认构造函数是trivial,因此,需要合成默认构造函数。

4 当类采用虚继承方式时

当类采用虚继承方式时,在生成对象时,编译器需要在每个派生类的对象中安插虚基类的地址,它们的默认构造函数也是trivial,因此,需要合成默认构造函数。

小结:

上面四种情况下,需要合成默认构造函数,这些情况都是与类有关,也就是说,当编译器在构造对象或者实现虚拟机制时,默认构造函数需要干一些有用的事,因此它们的默认构造函数是trivial,只有这样它们才需要构造。而对于基本数据类型和字符串,就需要程序员来处理了。

下面再来看看拷贝构造函数的情况。

何时会调用拷贝构造函数?

(1)用一个对象初始化另一个对象时,当然,它们要是同类对象;

(2)当函数的参数是对象,通过对象调用函数时,参数的拷贝会调用拷贝构造函数;

(3)当函数的返回值是对象,调用函数时,返回一个对象会调用拷贝构造函数。

当类中没有定义显示的拷贝构造函数,会合成拷贝构造函数,那么,具体什么情况下会合成拷贝构造函数呢?

同合成的默认构造函数类似,当编译器认为合成的拷贝构造函数需要来完成一些必要的任务时,才需要合成拷贝构造函数。如果编译器认为能够仅仅依靠逐个拷贝操作来完成,就不会合成拷贝构造函数,当然,编译器并不保证逐个拷贝操作能够保证正确的语义。

下列情况下,编译器会合成拷贝构造函数:

1 当类中含有类对象成员时

当类中含有类对象成员,而且类对象成员有拷贝构造函数(显示定义和合成的都可以),编译器就会合成拷贝构造函数,并安插调用类对象成员拷贝构造函数的代码。

2 当基类有拷贝构造函数时

当类继承另一个类,而且基类有拷贝构造函数(显示定义和合成的都可以)时,编译器就会合成拷贝构造函数,并安插调用基类拷贝构造函数的代码。

3 当类中有虚函数时

如果类中有虚函数,在复制过程中要设置左边的对象的虚函数表的地址,因此,完全的逐个拷贝操作不行,编译器就会合成拷贝构造函数,进行虚函数表的地址的设置。

4 当类采用虚继承方式时

当类采用虚继承方式,在复制过程中要在左边的对象安插虚基类的地址,因此,不能逐个拷贝,编译器就会合成拷贝构造函数,安插虚基类的地址。

小结:

与合成的默认构造函数类似,拷贝构造函数在逐个拷贝操作不能满足编译器时,编译器就会合成拷贝构造函数。而且这通常都与类和虚机制相关。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 默认构造函数