C++对象模式

非静态数据成员放置在每个类对象内,静态数据成员则被放置在所有类对象之外。静态和非静态的成员函数也被放置在所有类对象之外。每个类产生一堆指向虚函数的指针,放在虚表(vtbl)中。每个类对象维护一个指针(vptr),指向相关的虚表。虚表的首元素维护了每个类所关联的type_info对象。

优点:空间与存取时间效率高

缺点:一旦所用到的类对象的非静态数据成员有所修改,那么代码就要重新编译

加上继承

C++支持单一继承、多重继承和虚拟继承。在虚拟继承的情况下,基类不管在继承链中被派生多少次,永远只会存在一个实体。

C++中凡是处于同一个访问控制修饰符下的数据,必定保证以其生命的次序出现在内存布局中。然而被放置在多个访问控制修饰符下的各笔数据,内存的排布顺序就不一定了。同样的道理,基类和派生类的内存布局也没有谁先谁后的强制规定。虚函数也会对内存布局产生影响。

对象的差异

只有通过指针或者引用间接处理基类对象,才能支持面向对象程序设计所需的多态性质。

C++以下列方法支持多态:

  • 经由一组隐含的转化操作,例如把一个派生类指针转化为一个基类的指针
  • 经由虚函数机制
  • 经由dynamic_casttypeid运算符

类对象的内存

  • 其非静态数据成员的总和
  • 加上任何由于内存对齐而填补的空间
  • 加上为了支持虚函数而内部产生的额外负担

void*类型的指针只表示一个地址,不能够通过它操作所指的对象。类型转换其实是一种编译器指令,大部分情况下它不改变一个指针所含的真正地址,只影响“被指向的内存大小和其内容”的解释方式。

加上多态之后

class Bear : public ZooAnimal{
public:
Bear();
~Bear();
// ...
void rotate();
virtual void dance();
// ...
protected:
enum Dances { ... }; Dances dances_known;
int cell_block;
}; Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

这两个指针都指向Bear对象的首个字节,差别是pb所涵盖的地址包含整个Bear对象,而pz所涵盖的地址只包含Bear对象中的ZooAnimal部分。除了ZooAnimal对象中出现的成员,不能用pz直接处理Bear的任何成员,除非使用虚函数机制:

pz->cell_block;                       // 不合法
((Bear*)pz)->cell_block; // 合法
dynamic_cast<Bear*>(pz)->cell_block; // 合法
pb->cell_block; // 合法

当我们写下代码pz->rotate();时,pz的类型将在编译期决定以下两点:

  • 固定的可用接口,即pz只能调用ZooAnimalpublic接口
  • 该接口的访问权限

执行期pz所指的对象类型可以决定rotate()所调用的实体(即动态绑定)。类型信息的封装并不维护于pz中,而是维护于对象的虚函数指针和该指针所指的虚表之间

对于下面这种情况,为什么rotate()所调用的是ZooAnimal实体而不是Bear实体呢?此外,如果初始化函数(赋值操作)将一个对象的内容完整地拷贝到另一个对象中,为什么za的虚指针不指向Bear的虚表呢?

Bear b;
ZooAnimal za = b; // 会引起切割 // 调用 ZooAnimal::rotate()
za.rotate();

因为za本身是一个ZooAnimal对象而非Bear对象,所以它并不能调用Bear类型的方法。当一个基类对象被指定为派生类对象时,派生类就会被切割,以塞入较小的基类对象的内存中。因此,该基类对象就不能访问派生类的成员。而指针或者引用之所以支持多态,是因为它们不会引发内存中任何“与类型有关的内存委托操作”,改变的只是它们所指向的内存的“大小和内容解释方式”而已。

对于第二个问题,编译器在初始化和赋值操作之间做出了仲裁。编译器必须确保如果某个对象含有一个或一个以上的虚指针,那些虚指针的内容不会被基类对象初始化或改变。

《深度探索C++对象模型》第一章 | 关于对象的更多相关文章

  1. 深度探索c++对象模型 第一章

    1,声明与定义. //声明式如下: extern int x;   //对象式(变量式)声明 std::size_t numDigits(int number);  //函数式声明 class Wid ...

  2. 【C++】深度探索C++对象模型读书笔记--关于对象(Object Lessons)

    前言中的内容: 1.什么是C++对象模型? 1.语言中直接支持面向对象程序设计的部分 2. 对于各种支持的底层实现机制 2. C++ class的完整virtual functions在编译时期就固定 ...

  3. 《深度探索c++对象模型》chapter1关于对象对象模型

    在c++中,有2种class data member:static和nostatic,以及3钟class member function:static,nostatic和virtual.已知下面这个c ...

  4. 深度探索c++对象模型 第二章

    1,c++转换函数:显示转换和隐式转换. 隐式转换为程序员提供了很大的变量.比如整形提升,普通类型转换为类类型(operator int())都为程序带来无尽的方便.试想,如果没有整形提升,一个sho ...

  5. Android深度探索-卷1第一章心得体会

     本章介绍了安卓系统移植与驱动开发的概述,安卓的系统架构有四层:1 Linux内核,2 c/c++代码库, 3 Android SDK API, 4 应用程序 在读的过程中看到了专业名词,查了查,长点 ...

  6. 拾遗与填坑《深度探索C++对象模型》3.3节

    <深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...

  7. 拾遗与填坑《深度探索C++对象模型》3.2节

    <深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...

  8. 《深度探索C++对象模型》读书笔记(一)

    前言 今年中下旬就要找工作了,我计划从现在就开始准备一些面试中会问到的基础知识,包括C++.操作系统.计算机网络.算法和数据结构等.C++就先从这本<深度探索C++对象模型>开始.不同于& ...

  9. 深度探索C++对象模型

    深度探索C++对象模型 什么是C++对象模型: 语言中直接支持面向对象程序设计的部分. 对于各个支持的底层实现机制. 抽象性与实际性之间找出平衡点, 需要知识, 经验以及许多思考. 导读 这本书是C+ ...

  10. c++学习书籍推荐《深度探索C++对象模型》下载

    百度云及其他网盘下载地址:点我 百度云及其他网盘下载地址:点我 编辑推荐 如果你是一位C++程序员,渴望对于底层知识获得一个完整的了解,那么这本<深度探索C++对象模型>正适合你 作者简介 ...

随机推荐

  1. css处理工具PostCss

    在 Web 应用开发中,CSS 代码的编写是重要的一部分.CSS 规范从最初的 CSS1 到现在的 CSS3,再到 CSS 规范的下一步版本,规范本身一直在不断的发展演化之中.这给开发人员带来了效率上 ...

  2. vue特效网站集锦

    1.17素材网 http://www.17sucai.com/pins/tag/7012.html

  3. 在变压器厂中使用 ISA-95 应用程序进行调度集成

    介绍 在工业批量和连续生产/运营环境中,调度涉及将诸如罐.反应器和其他加工设备之类的资源分配给生产/运营任务.第 4 层生产/运营计划确定要制造什么产品.要制造多少产品以及何时制造.根据设备.物料.人 ...

  4. 【Java】单例设计模式

    文章目录 单例设计模式 什么是设计模式 单例设计模式 实现 饿汉式 懒汉式 饿汉式与懒汉式的区别 饿汉式 懒汉式 单例模式的应用场景 单例设计模式 什么是设计模式 设计模式是在大量的实践中总结和理论化 ...

  5. Genymotion安装apk问题

    Genymotion安装apk时,出现如下错误: 问题原因分析:很多apk使用arm架构的 cpu,在x86上安装会存在问题. 解决办法: 在Genymotion模拟器上安装一个能够解析ARM架构的a ...

  6. Solon Web 开发,七、视图模板与Mvc注解

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  7. SSM框架——thymeleaf学习总结

    本人关于thymeleaf的学习源自: https://www.bilibili.com/video/BV1qy4y117qi 1.thymeleaf的项目搭建 首先创建springboot项目,相关 ...

  8. 【解决了一个小问题】golang xorm中使用where id in (xxx),没办法使用参数替换

    代码中使用XORM来从数据库查询数据,有类似如下的代码: session.Where("id in (?)", strings,Join(arr, ",")) ...

  9. 【记录一个问题】opencl enqueueWriteBuffer()中,cl_bool blocking参数设置无效

    err = queue.enqueueWriteBuffer(in_buf, true, 0, bmp_size, bmp_data, NULL, &event); 以上代码中,第二个参数设置 ...

  10. limit概述

    5.limit 5.1.limit是将查询结果集的一部分取出来,通常使用在分页查询中 分页作用是为了提高用户体验,可以一页一页翻页看 5.2.limit用法:(非常重要) 完整用法:limit sta ...