第二章 构造函数
一、缺省构造函数
构造函数令人烦恼的一点是总是在编写代码不知道的情况下产生。本章就是针对这个问题,说明构造函数在什么情况下产生。
构造函数的产生原则:在需要的时候产生!
那么什么时候是需要的时候呢?“需要”分为用户需要和编译器需要。如果用户需要在构造函数中初始化对象,那么,这是用户的责任,编译器是不会干预的。这是C++的原则,避免造成用户的困扰。
编译器有时候没有办法,也必须产生构造函数,这是我们需要了解的。本书阐述了四个条件下编译器会自动产生构造函数:
1、 类中有带有default constructor的成员对象
如果一个类中包含有default constructor的对象,那么编译器就会自动产生一个构造函数,讲这个对象初始化。编译器做这个操作时不对任何其他变量进行初始化;
如果用户设计一个构造函数,将某个自己的变量初始化,且这个类中有对象有自己的default constructor,那么在用户自己的构造函数中,将被加入一些代码,初始化有default constructor的对象。
其实很好理解,原则是编译器尽量不背着用户使用构造函数。但是,如果类中一个对象本身有default constructor了,用户期望当用到这个类时已经被初始化了,所以,编译器做了构建构造函数的操作,满足用户的期望。如果不这么做,用户会很迷惑,明明定义了构造函数,而抱怨编译器什么都不做。
2、 带有default constructor的基类
道理跟1类似。因为基类中定义了default constructor,那么用户理解派生类中也应该被初始化。
3、 带有virtual function的类
这时生成default constructor来初始化vptr。也是无奈之举。
4、 带有一个virtual base class的类
编译器会构造default constructor,目的是使“允许每一个virtual base class的执行期存取操作”。(不是很懂。以后回来看)
二、拷贝构造函数
拷贝构造函数的作用?何时需要构建拷贝构造函数?拷贝构造函数与编译器优化之间的关系?这是本节主要要解决的问题。
拷贝构造函数的声明格式为
X::X(const X& x);
拷贝构造函数使用的地方主要有三个地方:复制一个类对象(也可以通过定义opertor=来实现)、对象作为一个参数交给某个函数、及函数传回一个类对象时用到。
构建拷贝构造函数主要有三种方式:一种是用户自己定义拷贝构造函数,这种方式的优先级最高,程序将优先使用这种方式复制对象,至于程序的效率取决于用户的水平;如果用户没有定义拷贝构造函数,那么系统会尝试使用bitwise copy的方式复制对象,这种方式的效率最高,编译器如果优化得比较好,将尽量采取这种方式;最后一种,是当bitwise copy失效的情况下,编译器将自己产生拷贝构造函数,这种方法效率较低。接着,介绍了bitwise copy失效的几种情况:
1、 类中含有对象,而该对象已经被声明了拷贝构造函数;
原因见缺省构造函数的原因1。
2、 类继承自一个基类,而基类中包含了拷贝构造函数;
原因见缺省构造函数原因2。
3、 当类中有虚函数时;
A, 如果类B、类C都继承自类A,那么,C给B赋值时,由于B、C使用同一个virtual table,所以使用bitwise copy的方式复制vptr是没有问题的,拷贝构造函数不会被构造;
如果 C 给 A 赋值,由于 A 、 C 使用不同的 virtual table , vptr 也不一样,所以编译器会构造一个拷贝构造函数,对 A 的 vptr 赋不同的值。
|