深入探索默认构造函数

问题:传统认识为:如果我们自己在类中没有定义任何构造函数,那么编译器就会为我们隐式自动生成一个默认的构造函数,我们称这种构造函数为“合成的默认构造函数”。事实的真相果真如此吗?

结论:“合成默认构造函数”,只有在必要的时候,编译器才会为我们自动合成出来,而不是必然为我们合成出来。那到底什么时候是必要的呢?

代码演示:

#include <iostream>

using namespace std;

class MATX
{
public:
	MATX()
	{
		cout << "MATX() 调用了" << endl;
	}
};

class MBTX
{
public:
	int m_i;
	int m_j;
	MATX m_a;

	void funct()
	{
		cout << "IamVeryGood!" << endl;
	}
};

int main()
{	
	MBTX myb;

   //dumpbin /all test.obj > test.txt 生成test.txt之后,查找MBTX::MBTX就可以观察到编译器是否为我们合成默认构造函数 
   //MBTX::MBTX

	return 0;
}

结论(1): 该类MBTX没有任何构造函数,但是包含一个类型的成员m_a,而该对象m_a所属的类MATX有一个缺省的构造函数,这个时候编译器就会该类MBTX合成一个默认的构造函数,合成的目的是为了调用MATX里的默认构造函数。换句话说:编译器合成了默认的MBTX的构造函数,并且在其中安插代码,调用MATX的缺省构造函数。

代码演示:

#include <iostream>

using namespace std;

class MATX
{
public:
	MATX()
	{
		cout << "MATX() 调用了" << endl;
	}
};

class MBTXParent
{
public:
	MBTXParent()
	{
		cout << "MBTXParent() 调用了" << endl;
	}
};
class MBTX:public MBTXParent
{
public:
	int m_i;
	int m_j;
	//MATX m_a;

	void funct()
	{
		cout << "IamVeryGood!" << endl;
	}
};

int main()
{	
	MBTX myb;

   //dumpbin /all test.obj > test.txt 生成test.txt之后,查找MBTX::MBTX就可以观察到编译器是否为我们合成默认构造函数 

	return 0;
}

结论(2): 父类带缺省构造函数,子类没有任何构造函数。原因:子类必须合成一个默认的构造函数,来调用父类这个缺省的构造函数。合成的目的就是为了调用这个父类的构造函数。换句话说:编译器合成了默认的构造函数,并在其中安插代码,调用父类的缺省构造函数。

结论(3):如果一个类中含有虚函数,但是这个类没有任何的构造函数的时候,编译器就会为该类生成一个默认的构造函数。为什么呢?因为有虚函数的存在。第一点:编译器会给我们生成一个基于该类的虚函数表vftable。第二点:在这个默认构造函数中,把类的虚函数表地址赋值给对象的虚函数表指针。(因为对象的首部的虚函数指针必须正确的指向类的虚函数表,这样才能够发生多态。)需要说一点,当我们自定义了一个默认构造函数的时候,编译器会根据需要扩充默认构造函数。

 

结论(4):如果一个类带有虚基类,编译器也会为它合成一个默认构造函数。

虚基类:通过两个直接基类继承通一个间接基类。所以一般是三成,有爷爷Grand,有两个爹A,A2,有孙子C。

vbtable虚基类表。vftable虚函数表。为什么会产生一个默认构造函数呢,我猜想原因大致如下:在默认构造函数中,将虚基类表的地址赋值给对象的虚基类表指针。

代码演示:

#include <iostream>

using namespace std;

class Grand
{
public:

};

class A :virtual public Grand //编译器会为A生成一个虚基类表 vbtable
{

};

class A2 :virtual public Grand //编译器会为B生成一个虚基类表 vbtable
{

};

class C :public A, public A2 //编译器会为C生成一个默认构造函数
{

};

int main()
{	
	/*cout << "sizeof(Grand)=" << sizeof(Grand) << endl;
	cout << "sizeof(A)=" << sizeof(A) << endl;
	cout << "sizeof(A2)=" << sizeof(A2) << endl;
	cout << "sizeof(C)=" << sizeof(C) << endl;*/

	C cc;

   //dumpbin /all test.obj > test.txt 生成test.txt之后,查找MBTX::MBTX就可以观察到编译器是否为我们合成默认构造函数 

	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值