默认构造函数(缺省构造函数):没有参数的构造函数;
传统认识认为:如果我们自己没定义任何构造函数,那么编译器就会为我们隐式自动定义 一个默认的构造函数,我们称这种构造函数为:“合成的默认构造函数”.
其实不是这样的,只有在必要的时候,编译器才会为我们合成出来,而不是必然或者必须为我们合成出来。
必要的时候 是什么时候呢?
class TestA
{
public:
TestA(){
cout << "TestA::TestA()" << endl;
}
};
class TestB
{
public:
int a;
int b;
void func()
{
cout << "IAmAStudent" << endl;
}
};
int main()
{
TestB testB;
return 0;
}
我们定义了TestB对象,该对象没有默认构造函数.编译这个文件,找到编译中生成的obj文件,这个文件的位置是在与源文件同级的debug目录下面.
然后打开vs2013开发人员命令提示窗口
切换到main.obj(我们的名字可能不一样)所在目录,
执行以下命令
dumpbin /all main.obj > parse.txt
用dumpbin把.obj文件内容导出成可查看文件parse.txt,这个parse.txt格式,一般被认为是COFF:通用对象文件格式(Common Object File Format);
用记事本或其它软件打开这个文件,搜索TestB::TestB,为什么要搜索这个字符串呢,因为构造函数就是这个样子.
我们发现找不到,说明编译器并没有给我们生成默认构造函数.
class TestA
{
public:
TestA(){
cout << "TestA::TestA()" << endl;
}
};
class TestB
{
public:
int a;
int b;
TestA testA; //类类型成员
void func()
{
cout << "IAmAStudent" << endl;
}
};
int main()
{
TestB testB;
return 0;
}
和刚刚不一样的是这段代码中TestB中多了一个类类型成员,我们再次编译,然后执行刚刚执行的那段命令,打开parse.txt文件
我们发现我们找到了,编译器给我们生成了默认构造函数.
这里类TestA中我们声明了一个默认构造函数,如果我们不声明默认构造函数,即使TesB中有类类型成员,编译器也不会为我们生成默认构造函数的
#include<iostream>
using namespace std;
class TestA
{
public:
TestA(){
cout << "TestA::TestA()" << endl;
}
};
class TestC
{
public:
TestC(){
cout << "TestC::TestC()" << endl;
}
};
class TestB
{
public:
int a;
int b;
TestC testC;
TestA testA;
void func()
{
cout << "IAmAStudent" << endl;
}
};
int mian()
{
TestB testB;
return 0;
}
这段代码中,testB中多了一个类类型成员testC.编译后,把main.obj解析成parse.txt
我们发现在TestB的构造函数中先调用了TestC的构造函数,再调用了TestA的构造函数,这是因为TestC的对象定义在了TestA前面所以先构造了TestC后构造TestA.如果TestA定义在TestC之前那么就会先构建TestA,再构造TestC.
该类TestB没有任何构造函数,但包含一个类类型的成员testA,而该对象testA所属于的类TestA有一个缺省的构造函数。
这个时候,编译器就会为该类TestB生成一个 “合成默认的构造函数”,合成的目的是为了调用TestA里的默认构造函数。
换句话说:编译器合成了默认的TestB构造函数,并且在其中 安插代码,调用TestA的缺省构造函数.