深入探索C++对象模型--指针类型 & 多态机制

指针的类型

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

1、  一个指向地址1000的整数地址,在32位机器上,将涵盖地址空间1000~1003

2、  那么,一个指向地址1000而类型为void*的指针,将涵盖怎样的地址空间呢?这个不知道,这就是为什么一个类型为void*的指针只能够含有一个地址,而不能通过它操作所指之对象的缘故。

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

Class ZooAnimal{

Public:

ZooAnimal();

Virtual~ZooAnimal();

Virtualvoid rotate();

Protected:

Intloc;

Stringname;

};

Class bear:public ZooAnimal

{

Public:

Bear();

~Bear()

Voidrotate();

Viratul void dance();

Protected:

Int cell_block;

};

但是考虑多态以后呢?加入Bear继承了ZooAnimal  同时是Public继承

Bear b;

ZooAnimal *pz = &b;

Bear* pb = &b;

他们每个都指向Bear对象的第一个字节,其间的差别是,pb所涵盖的地址包含整个Bear对象,而pz所涵盖的地址只包含Bear对象中的ZooAnimal子对象

除了在ZooAnimal中出现的成员,你不能够实用pz来直接处理Bear的任何成员。唯一例外的是通过virtual机制。

Pz->cell_block;

//不正确,cell_block不是ZooAnimal的一个成员,虽然我们知道pz当前指向一个Bear对象

((Bear*)pz)->cell_block;

//合法 经过一个明白的转型操作就没有问题

Pb->cell_block;

//合法  因为cell_block是Bear的一个成员

但是当我们写

Pz->rotate();时,(rotate是虚拟函数)pz的类型将在编译使其决定一下两点:

固定的可用接口,也就是说,pz只能够调用ZooAnimal的Public接口

该接口的访问级别(例如rotate()是ZooAnimal的一个public成员)

在每一个执行点,pz所指的对象类型可以决定rotate()所调用的实体,类型信息的封装并不是维护与pz之中,而是维护与link之中,此Link存在于对象的vptr和vptr所指的virtual table之间,在每一个virtual table中都有一个信息是type of info的信息

Bear b;

ZooAnimal za = b; //这样会引起切割

Za.rotate();  //调用ZooAnimal::rotate()

为什么rotate()所调用的是ZooAnimal实体而不是Bear实体?为什么za的vptr不指向Bear的virtual table

编译器在初始化以及赋值操作(将一个对象赋值给另一个对象)之间做了仲裁,编译器必须确保如果某个对象含有一个或一个以上的vptrs,那么vptrs的内容不会被基类对象初始化或改变

加入ZooAnimal->Bear->Panda  继承关系

ZooAnimal za;

ZooAnimal * pza;

Bear b;

Panda* pp = new Panda;

Pza = *b

将za或b的地址,或pp所含的内容(也是个地址)指定给pza,显然不是问题,一个指针或一个引用值所以支持多态,是因为它们并不引发内存中任何“与类型有关的内存委托操作”,会受到改变的只是它们所指向的内存的“大小和内容解释方式”而已。

所谓与类型有关的内存委托操作是指这个类型被编译所认识的大小,比如上面使用pz->cell_block.

大小和内容解释方式是在编译期间发生的,但是对于多态来说,是一个函数,但是函数是不依附于对象的,如果只要访问的对象中存在这个函数并且这个函数的访问级别可以达到,编译期间就可以实现,但是等到运行期间,如果发现这个函数是一个虚函数,这个时候在虚函数表中的第一个位置就是关于这个类型的所有信息,这个时候就会知道这个对象对应的真实类型是什么。需要分清这两点的差异

时间: 2024-11-05 13:04:25

深入探索C++对象模型--指针类型 & 多态机制的相关文章

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

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

【深度探索C++对象模型】第一章 关于对象

第一章 关于对象(Object Lessons) -- 本书作者:Stanley B.Lippman 一.前言 什么是 C++ 对象模型:简单的说,就是 C++ 中面向对象的底层实现机制. 本书组织: 第 1 章,关于对象(Object Lessons),介绍 C++ 对象的基础概念,给读者一个粗略的了解. 第 2 章,构造函数语意学(The Semantics of Constructors),构造函数什么时候会被编译器合成?它给我们的程序效率带来了怎样的影响? 第 3 章,Data语意学(T

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

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

《深度探索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++对象模型-&gt;1.3对象的差异

一.C++程序设计直接支持三种程序设计模式(programming paradigms),程序模型.程序数据类型模型(OB).面向对象模型(OO) 1.程序模型:类似C语言,用过程型语句组成. 2.抽象数据类型模型:所谓抽象就是讲实现和接口分离,显示提供接口,隐藏实现.(PS:不支持虚函数和多态). 3.面向对象模型:通过一个抽象的base class(用以提供共同的接口),将一系列有关联的类型封装起来.通过引用和指针来提供多态. 二.一个Class object共需要多少内存来表示呢? 1.其

深度探索C++对象模型第6章 执行期语意学

(一)对象的构造和析构(Object Construction and Destruction) 一般而言我们会把object尽可能放置在使用它的那个程序区段附近,这么做可以节省非必要的对象产生操作和摧毁操作. 全局对象 如果我们有以下程序片段: Matrix identity main() { //identity 必须在此处被初始化 Matrix m1=identity; ... return 0; } C++保证,一定会在main()函数中第一次用到identity之前,把identity

[转]《深度探索C++对象模型》读书笔记[一]

前 言 Stanley B.Lippman1.   任何对象模型都需要的三种转换风味: ü        与编译器息息相关的转换 ü        语言语义转换 ü        程序代码和对象模型的转换 2.   C++对象模型的两种解释 ü        语言中直接支持面向对象程序设计的部分 ü        对于各种支持的底层实现机制 3.   C++ class的完整virtual functions在编译时期就固定下来了,程序员没有办法在执行期动态增加或取代其中某一个.这使得虚拟函数调

【深度探索c++对象模型】Function语义学之虚函数

虚函数的一般实现模型:每一个class有一个virtual table,内含该class之中有作用的virtual function的地址,然后每个object有一个vptr,指向virtual table. 识别class是否支持多态,唯一恰当的方法是看它是否有virtual function,只要class拥有virtual function,它就需要额外的执行期信息. 考虑ptr->z(),ptr是基类指针,z是虚函数,为了找到并调用z()的适当实体,我们需要两项信息: 1.ptr所指对象

《深度探索C++对象模型(Inside The C++ Object Model )》学习笔记

转载:http://dsqiu.iteye.com/blog/1669614 第一章 关于对象 使用class封装之后的布局成本: class并没有增加成本,data members直接内含在每一个class object之中,就像C struct一样.而member functions虽然被包含在class的声明之内,但是不出现在Object之中.每一个non-inline function 只会产生一个函数实体.至于inline function则会在每一个调用使用的地方产生一个函数实体(在