10.2 每个对象都有默认的构造函数吗

有些C++类图书在介绍构造函数时会提及,当没有定义构造函数时,编译器会提供默认的构造函数,这个函数什么事情都不做,其内容类似于“{}”的形式。但是笔者经过研究发现,编译器不会在任何情况下都提供默认的构造函数。在许多情况下,编译器并没有提供默认的构造函数,而且经过O2选项优化编译后,某些结构简单的类会被转换为几个连续定义的变量,哪里还会需要构造函数呢?在前面的学习过程中,我们也碰到了在类对象定义过程中没有触发构造函数的情况,如代码清单10-6。

代码清单10-6 没有定义构造函数的类—C++源码


class CInit{

public:

void SetNumber(int nNumber){

m_nNumber=nNumber;

}

int GetNumber(){

return m_nNumber;

}

private:

int m_nNumber;

};

int main(int argc, char*argv[]){

CInit Init;

Init.SetNumber(5);

printf("%d",Init.GetNumber());

}


代码清单10-6中没有构造函数的定义,编译器会为类CInit提供默认的构造函数吗?答案见图10-2中对象Init的定义过程。

图 10-2 对象Init的定义过程

在图10-2中,对象Init的定义处没有任何对应的汇编代码,也没有构造函数的调用过程,可见编译器并没有为其提供默认的构造函数。那么,在何种情况下编译器会提供默认的构造函数呢?有以下两种情况:

本类、本类中定义的成员对象或者父类中有虚函数存在

由于需要初始化虚表,且这个工作理应在构造函数中隐式完成,因此在没有定义构造函数的情况下,编译器会添加默认的构造函数用于隐式完成虚表的初始化工作(详细讲解见第11章)。

父类或本类中定义的成员对象带有构造函数

在对象被定义时,由于对象本身为派生类,因此构造顺序是先构造父类再构造自身。当父类中带有构造函数时,将会调用父类构造函数,而这个调用过程需要在构造函数内完成,因此编译器添加了默认的构造函数来完成这个调用过程(详细讲解见第12章)。成员对象带有构造函数的情况与此相同。

在没有定义构造函数的情况下,当类中没有虚函数存在,父类和成员对象也没有定义构造函数时,提供默认的构造函数已没有任何意义,只会降低程序的执行效率,因此VC++6.0没有对这种情况下的类提供默认的构造函数。关于虚函数与类的继承关系会在以后的章节中详细讲解。