深入探索C++对象模型--对象模型

C++对象模型

C++中数据成员有两种:static和nonstatic,以及三种classmember functions:static nonstatic和virtual

现在标准C++对象模型:

Nonstatic data Members被置于每一个classobject之内,static data members则被存放在所有的class object之外,static和nonstatic function members也被放在所有的class object之外,virtual  functions则以两个步骤支持:

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

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

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

虽然你可以直接或间接处理继承体系中的一个base class object,但只有通过pointer或reference的间接处理,才支持OO程序设计所需的多态性质。这句话的意思是可以通过指针或引用来完成多态的目的。

也就是说,只有通过引用或指针才可能实现virtual机制。

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

其nonstatic members的总和大小:

加上任何犹豫alignment(对齐)的需求而填补(padding)上去的空间(可能存在于members之间,也可能存在于集合体边界)

加上为了支持virtual 而由内部产生的任何额外负担。

对于指针类型的理解:

同时需要说明一点,一个指针(或一个引用),不管它指向哪一种数据类型,指针本身所需的内存大小是固定的。所以对于任何类型的指针或引用,它所占用的空间大小是固定的。

既然一个指针无论指向哪一种类型,他们的内存大小是固定的,那么如何判断指向不同类型的指针时不同的呢?比如一个指向整数的指针或一个指向对象的指针有所不同呢?

从内存需求观点来说,没有什么不同!他们三个都需要有足够的内存来放置一个机器地址。“指向不同类型之各指针”间的差异,既不在其指针表示法不同,也不再其内容(代表一个地址)不同,而是在其所寻址出来的object类型不同,也就是说,“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小。也就是说,编译器知道某个指针所指向的空间的大小。比如一个指向整形的指针所指向的空间大小就是4个字节。指向一个对象的指针所指向的空间的大小就是这个对象的大小。

那么问题又来了,一个指向地址1000而类型为void*的指针,将涵盖怎样的地址空间呢?我们不知道,这就是为什么一个类型为void*的指针只能够含有一个地址,而不能够通过它操作所指之object的缘故。所以,转型其实是一种编译器指令,大部分情况下它并不改变一个指针所含的真正地址,它只影响“被指出之内存的大小和其内容”的解释方式。

如果在多态的情况下使用指针呢?

来看看在多态情况下指针的作用,假如有一个基类ZooAnimal,一个子类Bear,那么

Bear  b;

ZooAnimal* pz =&b;

Bear* pb=&b;

这么一来,pz pb的大小都是一定的,假设b存储的地址是1000,那么这两个指针有什么不同呢?它们每个都指向Bear object的第一个byte,差别是,pb所涵盖的地址包含真个Bear object,而pz所涵盖的地址只包含Bear object中的ZooAnimal subobject.

除了ZooAnimal subobject中出现的members,你不能够实用pz来直接处理Bear的任何members,唯一的例外是通过virtual机制。如果有了virtual机制,在执行的时候会在vptr尽心相关的type_info查看。

一个pointer或一个reference值所以支持多态,是因为他们并不引发内存中任何“与类型有关的内存委托操作”,会受到改变的只是他们所指向的内存的“大小和内容解释方式”而已。也就是说,指向不同类型的指针,其在编译期间会决定这个指针所指向的内存的大小和内容的解释方法。比如指向int的指针,在编译的时候已经确定,这个指针指向的内存大小为4字节内容是一个int。比如指向struct的指针,在编译的时候已经确定,这个指针指向的内存大小为sizeof(struct),指向的内容是这个struct中的内容。对于指针参与到virtual机制时,是另外的一个考虑。

时间: 2024-10-06 14:55:39

深入探索C++对象模型--对象模型的相关文章

探索单继承对象模型

探索单继承对象模型 class Base { public : virtual void func1() { cout<<"Base::func1" <<endl; } virtual void func2() { cout<<"Base::func2" <<endl; } private : int a ; }; class Derive :public Base { public : virtual void fu

c++对象模型-对象模型

1:简单对象模型 1>介绍:每个成员都使用一个指针指向真正的成员.所以对象 的大小很好确定,就是成员数*指针大小. 2>用途:成员函数就是使用这个模型的 3>图: 4>加上继承:每增加一个基类,就多一个指针. 2:表格驱动对象模型 1>介绍:把所有和members相关的信息抽出来,放在data member table 和 member function table中 2>用途:virtual function 3>图: 4>加上继承:增加一个base ta

深度探索C++对象模型 读书总结

Stanley B. Lippman 著 侯捷 译 这本书不是讲具体的C++编程技巧的, 涉及的内容并不在C++的语言层面, 而是探索一个C++编译器如何来实现C++的对象模型. 作者Lippman是世界上一个C++编译器cfront的主要开发者之一. C++最重要的特性继承和多态使如何来实现的呢? 使用多态带来的效率损失又是多少? 多重继承和虚拟继承又是如何实现的, 与单一继承和非虚拟继承之间的效率对比又是如何估算?  作者通过讲解当初他设计cfront编译器时遇到的这些问题及解决办法带领读者

VSTO学习笔记(二)Excel对象模型

原文:VSTO学习笔记(二)Excel对象模型 上一次主要学习了VSTO的发展历史及其历代版本的新特性,概述了VSTO对开发人员的帮助和效率提升.从这次开始,将从VSTO 4.0开始,逐一探讨VSTO开发中方方面面,本人接触VSTO时间不长,也是一次尝试.鉴于Excel在整个Office家族中的重要地位,故先从Excel开始介绍,后续内容会陆续介绍Word.PowerPoint.Outlook.InfoPath等.由于VSTO 4.0建立在Office 2010基础之上,先介绍一下Office

深度探索C++对象模型的读书心得

参考:深度探索C++对象模型 (stanley B.Lippman著 侯捷翻译) 1. Page9 : C++对象模型,说明每一个类仅有一个虚函数表Vtbl,而类的每一个对象都有指向其表的指针. 2. Page30:引用也需要与一个指针(大小为4BYTE)相同的空间. 3. Page28: 指针类型会教导编译器如何解释某个特定地址中的内存内容及大小. 4. Page39: explicit关键字能够制止"单一参数的constructor被当做一个Conversion运算符" 5. Pa

【深度探索C++对象模型】第二章 构造函数语意学(上)

第二章 构造函数语意学(The Semantics of Constructors) -- 本书作者:Stanley B.Lippman 一.前言 首先让我们来梳理一个概念: 默认构造函数(Default Constructor) : 是在没有显示提供初始化式时调用的构造函数.它由不带任何参数的构造函数,或是为所有形参提供默认实参的构造函数定义.如果定义的某个类的成员变量没有提供显示的初始化式时,就会调用默认构造函数(Default Contructor). 如果用户的类里面,没有显示的定义任何

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

2012年底-2014年初这段时间主要用C++做手游开发,时隔3年,重新拿起<深度探索C++对象模型>这本书,感觉生疏了很多,如果按前阵子的生疏度来说,现在不借助Visual Studio之类的工具的话,写C++代码感觉要比较费劲,最近重读了这本书后,感觉要写点东西下来(因为懒得用笔作笔记,太慢了-_-!)加深下印象. 以前还是新手的时候,总是认为: 1.class如果没有定义任何constructor的话,编译器会自动合成一个default constructor(我习惯叫缺省的构造函数)出

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

在c++中,有2种class data member:static和nostatic,以及3钟class member function:static,nostatic和virtual.已知下面这个class Point声明: class Point { public: Point(float xval); virtual ~Point(); float x() const; static int PointCount(); protected: virtual ostream& print(o

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

最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下: 例如,把单一元素的数组放在一个struct的尾端,于是每个struct objects可以拥有可变大小的数组.    code: struct mumble { //stuff char pc[1];    };        //从档案或标准输入装置中取得一个字符串,然后为struct本身和该字符串配置