以下内容转载自https://www.toutiao.com/i6584356542387061251/
考试紧张2018-07-31 20:35:19
首先问大家一个问题,何为C++对象模型?有些读者可能一时半会不知道怎么回答,或者还不理解这是什么意思。那就仔细的往下看吧。
C++对象模型可以概括为以下2部分:
1、语言中直接支持面向对象程序设计的部分;
2、对于各种支持的底层实现机制。
语言中直接支持面向对象程序设计的部分,如构造函数、析构函数、虚函数、继承(单继承、多继承、虚继承)、多态等等。本文重点介绍底层实现机制。
我们都知道在C语言中,“数据”和“处理数据的操作(函数)”是分开声明的,也就是说,语言本身并没有支持“数据和函数”之间的关联性。想想在C中,struct是不能申明函数的,只能通过间接的方式“函数指针”。在C++中,通过抽象数据类型(Abstract Data Type,ADT),在类中定义数据和函数,来实现数据和函数直接的绑定。概括来说,在C++类中有两种数据成员:static,nonstatic;三种成员函数:static、nonstatic、virtual。
例如下面的程序中展示的,麻雀虽小五脏俱全,程序虽短,但很典型。
#include<iostream>
using namespace std;
class Base
{
public:
Base(int);
virtual ~Base(void);
int getIBase() const;
static int instanceCount();
virtual void print() const;
protected:
int iBase;
static int count;
};
Base类在编译器中我们如何构建出各种成员数据和成员函数的呢?
为了让大家比较深刻的理解,以及为什么现在的对象模型是这样子的,我们从对象模型的演化历史开始吧。
基本C++对象模型
在介绍C++使用的对象模型之前,介绍2种对象模型:简单对象模型(A Simple Object Model)、表格驱动对象模型(A Table-Drive Object Model)。
简单对象模型(a simple object model)
所有的成员占用相同的空间(跟成员类型无关),对象只是维护了一个包含成员指针的一个表。表中放的是成员的地址,无论是成员变量还是函数,都是同样处理。对象并没有直接保存成员而只是保存了成员的指针。
表格对象模型(a table-driven object model)
这个模型在简单对象的基础上又添加了一个间接层。将函数和数据分别存储在两个表中,并保存了两个指向表格的指针。这个模型可以保证所有的对象具有相同的大小,比如简单对象模型还与成员的个数有关。其中数据成员表中包含实际数据;函数成员表中包含实际函数的地址(与数据成员相比,多一次寻址)。
C++对象模型
这个模型结合了上面两个模型的特点,并对内存存取和空间进行了优化。在此模型中,nonstatic数据成员被放置到对象内部,static数据成员、static和nonstatic函数成员军备放到对象之外。对于虚函数的支持则分两部分完成:
1、每一个class产生一堆指向虚函数的指针,并存放在虚函数表中(Virtual Table,vtbl);
2、每个对象被添加了一个指针,指向相关的虚函数表vtbl。通常这个指针被称为vptr。vptr的设定和重置都由每一个class的构造函数,析构函数和拷贝赋值运算符自动完成。
另外,虚函数表地址的前面设置了一个指向type_info的指针,RTTI(Run Time Type Identification)运行时类型识别是由编译器在编译时生成的特殊类型信息,包括对象继承关系,对象本身的描述。RTTI是为多态而生成的信息,所以只有具有虚函数的对象才会生成。
这个模型的优点在于它的空间和存取时间的效率;缺点如下:如果应用程序本身未改变,当所使用的类的nonstatic数据成员添加删除或修改时,需要重新编译。