标签:就会 static 虚拟 ber virt 共享 virtual members strong
先看一段代码
class X {}; class Y : public virtual X {}; class Z : public virtual X {}; class A : public Y, public Z {}; // sizeof(X)的结果为1 // sizeof(Y)的结果为8 // sizeof(Z)的结果为8 // sizeof(A)的结果为12
实际上,class X并不为空,它被编译器安插了一个隐藏的1 byte,这样使得class X的每个object在内存中拥有不同的地址。但是为什么class Y,class Z的sizeof大小是8呢?
class Y,class Z的大小受到三个因素的影响:
某些编译器(例如我用的vs2013)为我们提供了对empty virtual base class的特殊支持,就是将一个empty virtual base class视为derived class object最开头的一部分,也就是说derived class现在有member了,它不再是空了,也就不需要编译器安插那1 byte,自然也就不必为alignment padding提供3 bytes了。
现在它们的格局是上图这样的了。class Y,class Z的sizeof就是4 bytes了,当然class X还是一个empty class编译器依然会安插1 byte。那么class A的sizeof又会是8 bytes,因为它不存在base class subobject那1 bytes了。
对于virtual inheritance(虚拟继承)而言,在一个derived class中只会存在一份virtual base class subobject,因此,class A的大小由以下几点决定:
通过上面三点,可知class A的大小为12 bytes了。
c++ Standard并不强制规定“base class subobject的排列顺序”或“不同存取层级的data members的排列顺序”。data members是整个class在程序执行时的某种状态,nonstatic data members放置的是“个别的class object”感兴趣的数据。
早期的c++程序设计风格:
一个inline函数实体,在整个class声明未被完全看见前,是不会被评估求值的。如果inline在函数体内部,那么对函数的分析直至class声明的右大括号出现才开始。所以在inline member function躯体之内的一个data member绑定操作,会在整个class声明后才发生。即:
若取一个static data member地址,会得到得到数据类型的指针,而不是指向class member的指针,因为static member并不在任何一个class object。
若存取nonstatic data member,编译器需要把class object的起始地址+data member的偏移位置(offset)
origin.y=0.0; //那么&origin.y将等于 &origin+(&Point3d::y-1);
指向data member的指针,其offset值总是被加上1,这样编译器可以区分出“一个指向data member的指针,用以指向class的第一个member”和“一个指向data member的指针,没有指向任何member”两种情况。
标签:就会 static 虚拟 ber virt 共享 virtual members strong
原文地址:https://www.cnblogs.com/tianzeng/p/12109700.html