问题:传统认识为:如果我们自己在类中没有定义任何构造函数,那么编译器就会为我们隐式自动生成一个默认的构造函数,我们称这种构造函数为“合成的默认构造函数”。事实的真相果真如此吗?
结论:“合成默认构造函数”,只有在必要的时候,编译器才会为我们自动合成出来,而不是必然为我们合成出来。那到底什么时候是必要的呢?
代码演示:
#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;
}