2.4构造函数语义(编译器什么时候会生成默认构造)笔记

(168) 2024-04-05 14:01:01

一.什么是默认构造函数

默认构造函数(缺省构造函数):没有参数的构造函数;

二.编译器什么时候会为我们生成默认构造函数

        传统认识认为:如果我们自己没定义任何构造函数,那么编译器就会为我们隐式自动定义 一个默认的构造函数,我们称这种构造函数为:“合成的默认构造函数”.

        其实不是这样的,只有在必要的时候,编译器才会为我们合成出来,而不是必然或者必须为我们合成出来。
        必要的时候 是什么时候呢?

1.我们先看一段代码:

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目录下面.

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第1张

然后打开vs2013开发人员命令提示窗口

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第2张

 切换到main.obj(我们的名字可能不一样)所在目录,

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第3张

执行以下命令  

dumpbin /all main.obj > parse.txt

 用dumpbin把.obj文件内容导出成可查看文件parse.txt,这个parse.txt格式,一般被认为是COFF:通用对象文件格式(Common Object File Format);

用记事本或其它软件打开这个文件,搜索TestB::TestB,为什么要搜索这个字符串呢,因为构造函数就是这个样子.

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第4张

我们发现找不到,说明编译器并没有给我们生成默认构造函数.

2.再看一段代码

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文件

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第5张

我们发现我们找到了,编译器给我们生成了默认构造函数.

这里类TestA中我们声明了一个默认构造函数,如果我们不声明默认构造函数,即使TesB中有类类型成员,编译器也不会为我们生成默认构造函数的

3.再看一段代码:

#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

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第6张

2.4构造函数语义(编译器什么时候会生成默认构造)笔记 (https://mushiming.com/)  第7张 

 我们发现在TestB的构造函数中先调用了TestC的构造函数,再调用了TestA的构造函数,这是因为TestC的对象定义在了TestA前面所以先构造了TestC后构造TestA.如果TestA定义在TestC之前那么就会先构建TestA,再构造TestC.

三.总结

        该类TestB没有任何构造函数,但包含一个类类型的成员testA,而该对象testA所属于的类TestA有一个缺省的构造函数。
这个时候,编译器就会为该类TestB生成一个 “合成默认的构造函数”,合成的目的是为了调用TestA里的默认构造函数。
换句话说:编译器合成了默认的TestB构造函数,并且在其中 安插代码,调用TestA的缺省构造函数.

THE END

发表回复