C++对象模型《Inside the C++ Object Model》

一、C++对象模型

目前的C++对象模型是这样设计的。所有的nonstatic data members非静态成员数据,放在类对象中。所有的静态的数据成员,非静态函数,静态函数都放在类对象之外。

虚函数则是通过以下的方式实现:

  1. 每一个class产生一堆指向虚函数的指针,把指针放在一个表格中,这个表格被称为virtual table简称vtbl。
  2. 类对象中存放一个指向vtbl表格的指针,称为vptr。vptr在类对象中的位置,C++标准没有规定,编译器可以把它放在开始,中间或者末尾。但目前主流的做法是放在开始处,大多数编译器都是如此。RTTI使用到的type_info的内容,也是放在vtbl中,一般为第一个slot。vptr的设定和重置由每一个class的构造函数,拷贝构造函数,赋值函数自动完成。

虚继承则是会产生一个vbptr的指针指向虚基类。实现方式因编译器会略有不同。可以参照http://blog.csdn.net/sweetdark/article/details/8154775

实例:

class Point {
public:
    virtual ~Point();
    virtual void SetX(float x);
private:
    float _x;
    float _y;
};

 
 

类对象图:

C++对象模型《Inside the C++ Object Model》_第1张图片

二、非静态成员在内存中的顺序

C++标准规定,同一个访问段即private,public,protected。段中的成员在内存中的布局是按照其声明顺序的,但不同访问段内的成员在内存中的顺序C++标准没有规定,由编译器自由实现。

三、与C的兼容。

struct Point {
	float _x;
	float _y;
};


class Point2D : public Point {
public:	
virtual void getX();
};


Point2D的对象中多了一个vptr指针,与Point的内存布局已经不同,会产生程序的兼容性问题,例如Point *p = new Point2D;((char*)p + 4)在32位系统下,p是指向了_x。因为头四个字节是vptr。但是在原C程序中,Point *p = (Point*)malloc(sizeof(Point));((char*)p + 4)是指向_y的。C++要兼容C的较好的方式是通过,组合和转换运算符实现。如下:

class Point2D {
public:
	operator Point() { return p;}
private:
	Point p;
};
四、需要多少内存表现一个class object

  • nonstatic data members的总和大小。
  • 加上任何由于对齐需要填充的字节。
  • 加上为了支持virual机制,包括虚函数和虚基类而内部产生的额外负担。

你可能感兴趣的:(C++对象模型《Inside the C++ Object Model》)