explict关键字之所以被导入C++,是为了给程序员提供一种方法,使他们能够制止单一参数的构造函数被当做一个转换运算符。
《深入理解C++对象模型》关于C++默认构造函数什么时候并合成有四点要求。在介绍这四点要求之前,需要先了解虚基类是如何实现的?
虚基类是为了解决多重继承出现的二义性。
class X{public : int x;}
class A:virtual public X{public : int a;}
class B:virtual public X{public: int b;}
class C: public A,public B{public : int c}
在虚继承的下 C中只含有X中变量a的一个实例,而不是两个。也即,在虚继承的情况下,base class不管在继承串链中被派生多少次,永远只有一个实例。
一个派生类如何在本质上模塑其base class的实例ne?
在《深入理解C++对象模型》这本书中给出两种解释:
1.在简单对象模型中,将每一个派生类的slot指向基类,此slot即是基类的实例的地址。
2.base table模型。base class table中的每一个slot内含一个相关的base class地址,每一个类对象有一个指针指向其base class table。
因此 若声明了C的对象c: C c;
则c的布局如下:
vb_ptr:继承自A
int a
vb_ptr:继承自B
int b
int x
int c
首先,vb_ptr指向一个整数的地址,里面放的整数是那个int a的距离dD开始处的位移(在这里vb_ptr指向的地址里面放的是20,以字节为单位)。编译器是这样做的:
首先,找到vb_ptr(这个不用找,因为在g++中,vb_ptr就是B*中的第一项,呵呵),然后取得vb_ptr指向的地址的内容(这个例子是20),最后把这个内容与指针pb相加,就得到pb->a的地址了。
所以说这种时候,用指针转换多了两个中间层才能找到基类的成员,而且是运行期间。来自https://blog.youkuaiyun.com/a2796749/article/details/44014821
下面开始讲何时需要默认构造函数?
所谓默认构造函数的构建是当编译器需要的时候。并且并合成出来的构造函数只执行编译器所需要的行动。
何时是编译器需要呢?
1. 某些类中的成员包含一个有默认构造函数的类的对象,那么此时,这些类需要编译器合成默认构造函数。
2.带有默认构造函数的基类。也即某些类是某基类派生而来,且该基类含有默认构造函数,那么这些派生类需要编译器合成默认构造函数
3.含有虚函数的类,需要编译器合成默认构造函数。这是因为,需要编译器生成虚表
4.带有一个虚基类的类
编译器合成出来的默认构造函数并不会显示设定类中的每一个数据成员的默认值。
《深入理解C++对象模型》关于C++默认构造函数什么时候并合成有四点要求。在介绍这四点要求之前,需要先了解虚基类是如何实现的?
虚基类是为了解决多重继承出现的二义性。
class X{public : int x;}
class A:virtual public X{public : int a;}
class B:virtual public X{public: int b;}
class C: public A,public B{public : int c}
在虚继承的下 C中只含有X中变量a的一个实例,而不是两个。也即,在虚继承的情况下,base class不管在继承串链中被派生多少次,永远只有一个实例。
一个派生类如何在本质上模塑其base class的实例ne?
在《深入理解C++对象模型》这本书中给出两种解释:
1.在简单对象模型中,将每一个派生类的slot指向基类,此slot即是基类的实例的地址。
2.base table模型。base class table中的每一个slot内含一个相关的base class地址,每一个类对象有一个指针指向其base class table。
因此 若声明了C的对象c: C c;
则c的布局如下:
vb_ptr:继承自A
int a
vb_ptr:继承自B
int b
int x
int c
首先,vb_ptr指向一个整数的地址,里面放的整数是那个int a的距离dD开始处的位移(在这里vb_ptr指向的地址里面放的是20,以字节为单位)。编译器是这样做的:
首先,找到vb_ptr(这个不用找,因为在g++中,vb_ptr就是B*中的第一项,呵呵),然后取得vb_ptr指向的地址的内容(这个例子是20),最后把这个内容与指针pb相加,就得到pb->a的地址了。
所以说这种时候,用指针转换多了两个中间层才能找到基类的成员,而且是运行期间。来自https://blog.youkuaiyun.com/a2796749/article/details/44014821
下面开始讲何时需要默认构造函数?
所谓默认构造函数的构建是当编译器需要的时候。并且并合成出来的构造函数只执行编译器所需要的行动。
何时是编译器需要呢?
1. 某些类中的成员包含一个有默认构造函数的类的对象,那么此时,这些类需要编译器合成默认构造函数。
2.带有默认构造函数的基类。也即某些类是某基类派生而来,且该基类含有默认构造函数,那么这些派生类需要编译器合成默认构造函数
3.含有虚函数的类,需要编译器合成默认构造函数。这是因为,需要编译器生成虚表
4.带有一个虚基类的类
编译器合成出来的默认构造函数并不会显示设定类中的每一个数据成员的默认值。