对象 ######################################## 封装成本 **************************************** - C++所有对象之间共享成员函数 - 每个非内联函数只产生一个函数实体 - 每个内联函数将在每个使用内联函数的地方都拥有一份副本 .. note:: 内联函数这个特征很好理解,毕竟内联函数是被复制到使用内联函数的地方,而不是按地址调用 C++ 封装后的成本主要是由虚有函数和虚有基类造成的: - 虚有函数用于支持运行时绑定 - 虚有基类用来实现 ``多次出现在继承体系中的基类拥有单一、共享的实体`` 此外,子类与非第一基类之间的类型转换也会造成额外成本 对象模型 **************************************** C++根据对数据成员(静态数据成员、非静态数据成员)和成员函数(静态成员函数、非静态成员函数)的处理方式不同,构成了不同的对象模型: 简单对象模型 ======================================== 简单对象模型(Simple Object Model)中对象中只保存成员指针(数据成员指针和成员函数指针),此种情况下 ``对象的大小 = 指针的大小 x 指针的数量``。 .. image:: assets/简单对象模型.png 该对象模型降低了编译器的设计复杂度,代价是空间和执行期的效率。 这个模型并没有被应用于实际,但是为 ``指向成员的指针`` 提供了概念模型。 表格对象模型 ======================================== 表格对象模型(Table-driven Object Model)中,将数据成员和成员函数各自储存在一张表格中,对象则持有这两张表格的指针。数据成员表格中保存着数据成员的实体,而成员函数指针则保存着成员函数的指针。 .. image:: assets/表格对象模型.png 这个模型没有被应用于实际,但是为 ``虚函数`` 提供了概念模型 C++对象模型 ======================================== C++对象模型(C++ Object Model)描述如下: - 非静态数据成员储存到对象中 - 静态数据成员储存到对象之外 - 静态成员函数和非静态成员函数储存于对象之外 - 虚函数表的指针储存于对象之中 虚函数的支持方法如下: #. 建立虚函数表( :abbr:`vtbl (virtual table)` )储存指向虚函数的指针 #. 在对象中建立指向vtbl的指针(vptr)。vptr的初始化和销毁由构造函数、析构函数、复制构造函数自动完成。 #. 对象关联的 :abbr:`类型信息对象 (type_info object)` 被储存到vtbl的首部(通常情况下) .. image:: assets/C++对象模型.png 该模型的优点是空间和效率比较好,但是一旦类的非静态数据成员发生改变,整个软件代码必须要重新编译 C++继承模型 ======================================== #. 简单对象模型的继承模型 简单对象模型可以通过添加父类指针来储存基类,优点是子类大小与父类无关,但是带来了空间和效率的开销。 #. 基于表格的继承模型 通过构造 :abbr:`基类表 (base table)` 可以实现另一种继承模型,其特点为: - 基类表中包含指向基类的指针(多继承时包含多个基类指针) - 每个类对象都包含一个 ``指向基类表的指针(bptr)`` 其优点为无需更改类对象就可以更改基类,缺点是带来了储存空间和效率上的负担。 .. image:: assets/基于表格的继承模型.png C++编程范型 ======================================== C++支持三种编程范型: #. 过程式编程 例如: .. code-block:: cpp const char* boy = "Danny"; char* p_son; ... p_son = new char[ strlen(boy) + 1 ]; strcpy(p_son, boy); ... if(!strcmp(p_son, boy) take_to_disneyland(boy); #. 抽象数据模型(ADT) 抽象数据模型为用户提供借口,及内部计算过程隐而不提: .. code-block:: cpp string girl = "Anna" string daugher; ... daugher = girl; // operator=() ... if(girl == daugher) // operator==() take_to_disneyland(girl); #. 面向对象模型(Object-Oriented model) 面向对象模型通过抽象基类向外部提供接口,子类对接口进行实现。 .. code-block:: class Human{ public: virtual void eat() = 0; }; class Chinese: public Human{ public: void eat() override { cout<<"Chinease eat"<