再读《深入探索C++对象模型》笔记。

关于对象

C++在加入封装后(只含有数据成员和普通成员函数)的布局成本增加了多少?

  • 答案是并没有增加布局成本。就像C struct一样,memeber functions虽然含在class的声明之内,却不出现在object中。每一个non-inline member function只会诞生一个函数实体。至于每一个“拥有零个或一个定义的” inline function则会在其每一个使用者(模块)身上产生一个函数实体。

C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括:

  • virtual funciton机制,用以支持一个有效率的“执行期绑定”(runtime binding)
  • virtual base class,用以实现“多次出现在继承体系中的base class,有一个单一而被共享的实体”

C++ 对象模式(The C++ Object Model)

在C++中,有两种class data members:static 和 nonstatic,以及三种class member functions:static、nonstatic和virtual。已知下面这个class Point声明:

class Point{
public:
Point(float xval);
virtual ~Point();
float x() const;
static int PointCount(); protected:
virtual ostream& print(ostream &os) const;
float _x;
static int _point_count;
};

C++对象模型中,nonstatic data members被配置于每一个class object之内,static data members则被存放在所有的class object之外。static和nonstatic function members也被放在所有的class object之外。virtual function则以两个步骤支持之:

1. 每个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table(vtbl)

2. 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定和重置都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用以支持runtime type identification, RTTI)也经由virtual table被指出来,通常放在表格的第一个slot处

故上面的声明所对应的对象模型如下:

上图说明了C++对象模型如何应用于Point Class身上,这个模型的主要优点在于它的空间和存取时间的效率。主要缺点是:如果应用程序代码未曾改变,但所用到的class objects的nonstatic data members有所修改(有可能是增加、移除或更改),那么应用程序代码同样得重新编译。

继承关系可以指定为虚拟(virtual,也就是共享的意思):在虚拟继承的情况下,base class不管在继承链中被派生(derived)多少次,永远只会存在一个实例(称为subobject)。

class istream : virtual public ios{ ... };
class ostream : virtual public ios{ ... };

对象的差异

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

  • 经由一组隐式的转化操作。例如把一个derived class指针转化为一个指向其public base type的指针
  • 经由virtual function机制
  • 经由dynamic_cast和typeid运算符

多态的主要用途是经由一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中。这个共享接口是以virtual function机制引发的,它可以在执行期根据object的真正类型解析出到底是哪一个函数实体被调用。

需要多少内存才能表现一个class object?

  • 其nonstatic data members的总和大小
  • 加上任何由于aliginment的需求而填补上去的空间(可能存在于members之间,也可能存在于集合体边界)
  • 加上为了支持virtual而由内部产生的任何额外负担

一个指针(引用),不管它指向哪一种数据结构,指针本身所需的内存大小是固定的。

举例如下:一个指向ZooAnimal的指针是如何地与一个指向整数得指针或一个指向template Array的指针有所不同的呢?

ZooAnimal *px;
int *pi;
Array<string> *pta;

以内存需求的观点来说,没有什么不同!它们三个都需要足够的内存来放置一个机器地址(通常是个word)。“指向不同类型的各指针”间的差异,既不在其指针表示法不同,也不在其内容(代表一个地址)不同,而是在其所寻址出来的object类型不同,也就是说,“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小。

转型(cast)其实是一种编译器指令。大部分情况下它并不改变一个指针所含的真正地址,它只影响“被指出之内存大大小和其内容”的解释方式。

当一个base class object被直接初始化为(或被指定为)一个derived class object时,derived object就会被切割(sliced)以塞入较小的base type内存中,derived type将没有留下任何蛛丝马迹。多态于是不再呈现,而一个严格的编译器可以在编译器解析一个“通过此object而触发的virtual function调用操作”,因而回避virtual机制。如果virtual function被定义为inline,则更有效率上的大收获。

深入探索C++对象模型(一)的更多相关文章

  1. 读书笔记《深度探索c++对象模型》 概述

    <深度探索c++对象模型>这本书是我工作一段时间后想更深入了解C++的底层实现知识,如内存布局.模型.内存大小.继承.虚函数表等而阅读的:此外在很多面试或者工作中,对底层的知识的足够了解也 ...

  2. 柔性数组-读《深度探索C++对象模型》有感 (转载)

    最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下 ...

  3. 柔性数组-读《深度探索C++对象模型》有感

    最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下 ...

  4. [读书系列] 深度探索C++对象模型 初读

    2012年底-2014年初这段时间主要用C++做手游开发,时隔3年,重新拿起<深度探索C++对象模型>这本书,感觉生疏了很多,如果按前阵子的生疏度来说,现在不借助Visual Studio ...

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

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

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

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

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

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

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

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

  9. C++的黑科技(深入探索C++对象模型)

    周二面了腾讯,之前只投了TST内推,貌似就是TST面试了 其中有一个问题,“如何产生一个不能被继承的类”,这道题我反反复复只想到,将父类的构造函数私有,让子类不能调用,最后归结出一个单例模式,但面试官 ...

随机推荐

  1. Educational Codeforces Round 32 Problem 888C - K-Dominant Character

    1) Link to the problem: http://codeforces.com/contest/888/problem/C 2) Description: You are given a ...

  2. 【转载】Android 内存溢出如何发生的。

    [转载]Android 内存溢出如何发生的. 且谈Android内存溢出 前言 关于android的内存溢出在创新文档库中也有不少,网络上也有很多这方面的资料.所以这遍文章不算是正真意义上的创新,仅仅 ...

  3. 有道云笔记Markdown使用

    目录 使用规则 代码高亮 制作待办事项 高效绘图 基本规则 使用规则 代码高亮 #include <iostream> #include <string> using name ...

  4. 软件功能说明书——Thunder团队

    爱阅APP功能说明书 一.引言 相信大家都使用过电子书阅读器,相对于纸质版书籍电子书APP做到了环保.易存储.便携.因此我们Thunder团队开发了——爱阅APP,以下内容是Alpha版的功能说明书. ...

  5. C# 饼形图

    原文链接:https://www.cnblogs.com/icyJ/archive/2012/10/08/Chart_Pie.html 需要实现的目标是: 1.将数据绑定到pie的后台数据中,自动生成 ...

  6. 窗口中各模块的切换效果,使用jquery实现

    用到了两个js库,请自行下载,用到的背景图片可任意图片都可以,主要是看效果 <!DOCTYPE html> <html> <head> <script src ...

  7. C# 面向对象——多态

    多态分三种:1.虚方法 2.抽象类 3.接口 1.虚方法1.将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数可以被子类重新写一个遍. 如: class Program { static ...

  8. 源码安装和yum安装的区别。

    yum是将yum源中别人已经编译好的rpm包下载到本地,然后安装,不需要考虑依赖,主要是方便.源码安装没法人为的控制,安装的版本也很低. 源码安装需要自己编译,安装,编译过程中可以设置参数.可安装的版 ...

  9. [JLOI2014]松鼠的新家 树上差分

    差分 一开始竟然想分情况讨论来差分,然后发现各自情况要分析, 就是为了解决中间节点重复计算的问题, 结果 最后一想,中间重复计算了一次,那我最后减掉不就好了么,,, 那这就是一道差分裸题了(这是唯一不 ...

  10. BZOJ2301:[HAOI2011]Problem b——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2301 https://www.luogu.org/problemnew/show/P2522 对于给 ...