目录
③ 如果一个类带有虚基类,编译器也会为它合成一个默认构造函数
构造函数语义
①父类带缺省构造函数,子类没有任何构造函数
- 因为父类这个缺省的构造函数要被调用,所以编译器会为这个子类合成出一个默认构造函数。
- 合成的目的是为了调用这个父类的构造函数。
- 换句话说,编译器合成了默认的构造函数,并在其中安插代码,调用其父类的缺省构造函数。
#include <iostream> using namespace std; class MBTXPARENT { public: MBTXPARENT() { cout << "MBTXPARENT()" << endl; } }; class MBTX :public MBTXPARENT { public: int m_i; int m_j; MBTXPARENT m_mb; void funct() { cout << "IAmVeryGood" << endl; } }; int main() { MBTX myb; return 1; }
- 输出结果:
- 使用dumpbin进行测试
② 如果一个类含有虚函数,但 没有任何构造函数时
- 因为虚函数的存在:
- a) 编译器会给我们生成一个基于该类的虚函数表vftable
- b) 编译给我们合成了一个构造函数,并且在其中安插代码:
- 把类的虚函数表地址赋给类对象的虚函数表指针 (赋值语句/代码)
- 我们可以把 虚函数表指针 看成是我们表面上看不见的一个类的成员变量
- 为什么这么麻烦,因为虚函数的调用存在一个多态问题,所以需要用到虚函数表指针。
#include <iostream> using namespace std; class MBTX { public: int m_i; int m_j; void funct() { cout << "IAmVeryGood" << endl; } virtual void mvirfunc() { cout << "mvirfunc" << endl; } }; int main() { MBTX myb; return 1; }
- 使用dumpbin进行测试
- 自己实现缺省构造函数
class MBTX { public: int m_i; int m_j; void funct() { cout << "IAmVeryGood" << endl; } virtual void mvirfunc() { cout << "mvirfunc" << endl; } MBTX() { m_i = 15; } };
- 编译器给我们往MBTX缺省构造函数中增加了代码:
- (a)生成了类MBTX的虚函数表
- (b)调用了父类的构造函数
- (c)因为虚函数的存在,把类的虚函数表地址赋给对象的虚函数表指针。
- 我们有自己的默认构造函数时,编译器会根据需要扩充我们自己写的构造函数代码,比如调用父类构造函数,给对象的虚函数表指针赋值。
- 编译器干了很多事,没默认构造函数时必要情况下帮助我们合成默认构造函数,如果我们有默认构造函数,编译器会根据需要扩充默认构造函数里边的代码。
③ 如果一个类带有虚基类,编译器也会为它合成一个默认构造函数
- 虚基类:通过两个直接基类继承同一个简介基类。所以一般是三层 ,有爷爷Grand,有两个爹A,A2,有孙子C
#include <iostream> using namespace std; class Grand //爷爷类 { public: }; class A : virtual public Grand { public: }; class A2 : virtual public Grand { public: }; class C :public A, public A2 //这里不需要virtual { public: }; int main() { C cc; return 1; }
- 使用dumpbin进行测试
vbtable虚基类表 vftalble(虚函数表)
- 虚基类结构,编译器为子类和父类都产生了“合成的默认构造函数”
反汇编查看编译器添加了什么代码
- F9插入断点,F5运行,然后点击调试 - > 窗口 -> 反汇编
- 反汇编代码:
(C++对象模型):构造函数语义(下)
于 2020-09-17 20:18:44 首次发布