C++对象模型的一些有关问题

C++对象模型的一些问题

 

#include <iostream>
using namespace std;

class EmptyClass{};

class A
{
	virtual void show()
	{
		cout<<"A"<<endl;
	}
	virtual void Bshow(){}
	virtual ~A(){}
};
class B:public virtual A
{
	int b;
};
class C:public virtual A
{
	int c;
};
class D:public C,public B
{
	int d;
};

int main() {
	cout<<"size of EmptyClass:"<<sizeof( EmptyClass)<<endl;
	cout<<"size of A:"<<sizeof(A)<<endl;
	cout<<"size of B:"<<sizeof(B)<<endl;
	cout<<"size of C:"<<sizeof(C)<<endl;
	cout<<"size of D:"<<sizeof(D)<<endl;
	return 0;
}

 

     把这段代码解释通,就差不多可以理解C++基本对象模型了。

     可惜设计者为了避免某些问题而进行的尝试经常被使用的人忽略,导致一些误解,类的设计必然不能向人们期望的行为一样进行的。这就是折中,必要的牺牲啊。


    空类占一个Byte,这个如果不是看书我永远也不知道,至于为什么这样做,我现在也不明白。。

    只要类里出现虚函数,那么就涉及到一个vptr虚函数指针,指向一个虚函数表的。所以占用4Byte。我开始一直误解了,以为一个虚函数就是一个指针,当然一个指针指向一个表这样所占的空间少也更加合理些。内存的布局问题还涉及到占位符,就是为了方便系统快速存取所保留的字节数,默认是字段长也就是指针长度。


    虚继承的机制就有点复杂了,我现在还没搞清楚。但这里如果B和C不是虚继承自A的话,D将含有两个A里的变量,但由于我这例子A不含变量,也就没这样的问题了。


    以上只是一个开始。。。

 

12.14  不要在虚继承用的基类中声明非静态成员变量,不然就离复杂的深渊不远了。 虚继承的目的应该说是作为多重继承避免数据重复的,还有就是提供接口调用。之所以说不要这么做大部分原因是多重继承中编译器决策所调用函数时候涉及到Offset的复杂性。。我目前也一知半解,估计先记下。

 

12.15  看到了内联函数部分,然后查了一些以前不知道的关于内联的一些问题,这里列出:

关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。   定义在类声明之中的成员函数将自动地成为内联函数

内联最常出现的地方就是和#define 宏进行比较,宏是预处理,无法调试。内联函数说到底还是函数调用,可以声明变量,可跟踪。但这些需要编译器进行代码转换的,简单的模型就是直接将内联函数的代码伸展,而减少函数调用时候内存和栈的开销。实际情况当然很复杂了,所以内联的使用需要非常小心,经常会遇到的问题是编译器不支持,或者临时对象开销导致得不偿失。内联是个强有力的工具,但使用起来需要注意!