深入探索默认构造函数

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

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

代码演示:

#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;
}

 

posted @ 2020-03-22 12:54  repinkply  阅读(9)  评论(0)    收藏  举报