C++ 对象模型学习笔记四:分析obj目标文件-构造函数语义

  测试验证在什么情况下编译器自动为一个类创建“合成的默认构造函数”?及在一个类中定义多个其他类时和继承其他类时,调用其他类的构造函数顺序?

知识点:

 传统认识认为:如果我们自己没定义任何构造函数,那么编译器就会为我们隐式自动定义 一个默认的构造函数,我们称这种构造函数为:“合成的默认构造函数”
 结论:“合成的默认构造函数”,只有在 必要的时候,编译器才会为我们合成出来,而不是必然或者必须为我们合成出来。
编译器会在哪些必要的时候帮助我们把默认的构造函数合成出来呢?
  (1)、当类MBTX没有任何构造函数,但包含一个类类型的成员ma,而该对象ma所属于的类MATX 有一个缺省的构造函数。这个时候,编译器就会为该类MBTX生成一个 “合成默认的构造函数”,合成的目的是为了调用MATX里的默认构造函数。换句话说:编译器合成了默认的MBTX构造函数,并且在其中 安插代码,调用MATX的缺省构造函数;
  (2)、父类带缺省构造函数,子类没有任何构造函数,那因为父类这个缺省的构造函数要被调用,所以编译器会为这个子类合成出一个默认构造函数。
//合成的目的是为了调用这个父类的构造函数。换句话说,编译器合成了默认的构造函数,并在其中安插代码,调用其父类的缺省构造函数。
  (3)、如果一个类含有虚函数,但没有任何构造函数时因为虚函数的存在,
  a)编译器会给我们生成一个基于该类的虚函数表vftable。
  b)编译给我们合成了一个构造函数,并且在其中安插代码: 把类的虚函数表地址赋给类对象的虚函数表指针 (赋值语句/代码);
  我们可以把 虚函数表指针 看成是我们表面上看不见的一个类的成员函数,
  为什么这么麻烦,因为虚函数的调用存在一个多态问题,所以需要用到虚函数表指针。第三章详细讨论。
编译器给我们往MBTX缺省构造函数中增加了代码:
  (a)生成了类MBTX的虚函数表
  (b)调用了父类的构造函数
  (c)因为虚函数的存在,把类的虚函数表地址赋给对象的虚函数表指针。
  当我们有自己的默认构造函数时,编译器会根据需要扩充我们自己写的构造函数代码,比如调用父类构造函数,给对象的虚函数表指针赋值。
  编译器干了很多事,没默认构造函数时必要情况下帮助我们合成默认构造函数,如果我们有默认构造函数,编译器会根据需要扩充默认构造函数里边的代码。
  (4)、如果一个类带有虚基类,编译器也会为它合成一个默认构造函数。

分析cpp 生成的obj文件方法:

  在vs的开发人员命令提示符 下输入dumpbin命令、该命令用于分析obj文件,生成一个被认为是COFF:通用对象文件格式(Common Object File Format)。

  dumpbin /all  xxx.obj > xxx.txt  // 分析 xxx.obj 文件重定向到 xxx.txt文件中

测试代码如下:

#include <iostream>
using namespace std;

class M0TX
{
public:
	M0TX() //默认构造函数
	{
		cout << "wodeceshi" << endl;
	}
};
class MATX
{
public:
	MATX() //默认构造函数
	{
		cout << "goodHAHAHAHA" << endl;
	}
};

class MBTXPARENT
{
public:
	MBTXPARENT()
	{
		cout << "MBTXPARENT()" << endl;
	}
};
class MBTX :public MBTXPARENT
{
public:
	int m_i;
	int m_j;

	M0TX m0;  //类类型成员变量
	MATX ma; //类类型成员变量
	void funct()
	{
		cout << "IAmVeryGood" << endl;
	}

	virtual void mvirfunc()
	{
		cout << "mvirfunc" << endl;
	}

	MBTX()
	{
		m_i = 15;
	}
};

class Grand //爷爷类
{
public:
};

class A : virtual public Grand
{
public:
};

class A2 : virtual public Grand
{
public:
};

class C :public A, public A2 //这里不需要virtual
{
public:
	C()
	{
		int aa;
		aa = 1;
	}
};


int main()
{
	MBTX myb; //先输出"MBTXPARENT()" 后输出"wodeceshi" 再输出 "goodHAHAHAHA"  也就是说先执行MBTXPARENT的构造函数,再执行M0TX的构造函数,后执行MATX的构造函数,这顺序取决于先执行父类构造函数然后再取决于MBTX类中类定义顺序 

	//虚基类:通过两个直接基类继承同一个简介基类。所以一般是三层 ,有爷爷Grand,有两个爹A,A2,有孙子C
	C cc;
	system("pause");

	return 1;
}

运行结果:

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值