前言
提起构造函数,很多人都不陌生,在学习C++的时候,我们经常会听到“默认构造函数”的函数,并一直有一个传统认知,就是说在一个类的定义中,如果程序员没有定义任何构造函数的话,编译器会隐式地生成一个默认的构造函数,并称之为“合成默认构造函数”。那么,如果程序员没有定义任何构造函数,编译器是否会生成一个“合成默认构造函数”呢?我们接下来就来探索一下
前提知识
在C++中,如果要生成一个可执行文件,需要经过编译、链接的步骤,一个.cpp的文件,经过编译,就会生成一个.obj(或者.o)文件,这个文件也叫作目标文件,也就是说,.obj文件是编译的结果文件,而最终生成的可执行文件就是把这些.obj文件链接起来生成的。.obj文件属于二进制文件,不能直接看到里面的内容,但是可以借助一些工具来查看,以Windows平台工具为例,可以利用VS的dumpbin工具来查看
示例
现有以下代码
class MCAC
{
public:
MCAC()
{
cout << "construction complete" << endl;
}
};
class MCAX
{
public:
private:
int m_value;
};
int main()
{
MCAX m_obj;
return 0;
}
编译执行该段代码,在传统的认知中,编译器会为MCAX类生成一个“合成默认构造函数”,然而,事实果真如此吗? 让我们借助VS的dumpbin工具生成对应的.txt文件进行搜索 MCAX::MCAX 会发现根本搜索不到,也就是说:编译器根本没有合成该函数出来。 那么,编译器究竟在什么时候才会生成“合成默认构造函数呢” 1.编译器生成“合成默认构造函数”的第一种情况 ①如果该类没有任何构造函数 ②但包含一个类类型的成员变量
于是,我们在MCAX类中新增一个MCAC类型的成员变量
class MCAX
{
public:
private:
int m_value;
MCAC m_obj;
};
编译执行,并通过dumpbin工具生成.txt文件,搜索 MCAX::MCAX 发现 搜索到了 MCAX::MCAX 字样,并且在红线处还发现了 MCAC::MCAC ,也就是说调用了MCAC类的构造函数
再增加一个新类MCAY,该类也有默认构造函数
class MCAY
{
public:
MCAY()
{
cout << "construction complete" << endl;
}
};
同时在MCAX类中新增MCAY类型的成员变量
class MCAX
{
public:
private:
int m_value;
MCAC m_obj;
MCAY m_obj2;
};
编译执行,并利用dumpbin导出.txt文件 在RELOCATIONS中还看到了MCAX::MCAX先调用了MCAC::MCAC,再调用了MCAY::MCAY 如果我们将这两个成员变量的顺序调转一下,再编译,利用dumpbin工具生成.txt文件再查看,发现: 这一回MCAX::MCAX是先调用MCAY::MCAY,后调用MCAC::MCAC 与MCAX类中这两个成员变量的定义顺序一致
总结
通过探索,发现有以下情况,编译器会生成“合成默认构造函数” (1)该类没有任何构造函数但包含一个类类型的构造函数 (2)父类带有默认构造函数且子类没有任何构造函数 (3)一个类含有虚函数且该类没有任何构造函数 (4)一个类带有虚基类且该类没有任何构造函数 (5)在定义成员变量时赋初值,C++11支持这种写法
以上结论,均可以通过分析obj文件来进行观察佐证,在Windows下可以通过dumpbin工具
进行导出.txt文件分析 导出命令为:
dumpbin /all xx.obj > xx.txt
|