第1章 关于对象

2012-06-05 11:06:22

C++在布局及存取时间上主要额外负担是由virtual引起,将会在后面章节讨论C++布局问题。

本章一个重点讨论就是C++对象模式,这个内容非常重要,是基础,在后面将会被用到,尤其是涉及打virtual。

第1.1节 C++对象模型

简单对象模型

Members(指data member和function member)按照声明次序,各被指定一个slot。

图1.1说明这种模型

members本身并不放在object中,每一个slot存放的是“指向member的指针”,目的是避免members不同类型,导致占用不同存储空间带来的问题,一个class object大小等于指针大小乘以calss中声明members数目。

注意每一个slot固定大小,大小等于指针所占空间

表格驱动对象模型

区分data member 和function member,class只含有两个指针,一个指向member function table,一个指向data member table。

data member table直接含有数据,member function table则是一系列slot,每一个slot指出一个member function。

虽然这个模型也没有真正应用到C++编译器身上,但member function table这个观念却成为支持virtual functions的有效方案

图1.2说明这种模型

C++对象模型

1.静态数据成员和非虚函数成员放在class object体外

2.nonstatic data member放在每一个class object体内

3.虚函数采用表格驱动对象模型中对待function member的策略:

第一,每一个class产生出一堆指向虚函数指针,放在表格中,这个表格被称为virtual table(vtbl)

第二,每一个class object被添加了一个指针,指向相关的virtual table。通常这个指针被称为vptr。每一个class所关联的type_info object(用来支持runtime type identification,RTTI)也经由virtual table被指出来,通常放在表格slot处。

图1.3说明这种模型

问题:实际上对于type_info object作用还不是很清楚

加上继承

在虚继承情况下,base class不管在继承串链中被派生多少次,永远只会存在一个实体(称为subobject)。

base table模型

每一个class object内含有一个bptr,指向其base class table,base class table每一个slot内涵一个相关的base class地址,和virtual table内含每一个virtual function地址一样。

图1.4说明这种模型

优点:每一个class object对于继承都有一致的表现方式:第一,每一个class object都应该在某个固定位置上安放一个base table指针,与base classes大小和数量无关;第二,不需要改变class object本身,就可以放大,缩小,或更改base classtable。

缺点:间接性导致的空间和存取时间上的额外负担,这种间接性会随着继承的深度而增加。

个人观点:把members放在类体内减少了间接寻址次数,带来了时间和空间上的效率,同时也容易受到base class改变的影响,只能在二者之间寻求平衡

第1.2节 关键词带来的差异

如果不是为了努力维护与C之间的兼容性。C++远可以比现在更简单些。

核心问题:什么时候一个人应该在C++程序中以struct取代class?

从面向对象角度来说,不应该进行替换,struct更多意义上来说是C语言的遗留物,表达更多是一个数据集合体;而class则是包含数据和数据相应操作的抽象数据类型(ADT)。

之所以struct存在就是为了支持现存的C程序代码,因此struct更多可能是C++和C语言进行兼容的桥梁之一。

另一方面,class引入真的需要吗?从理性角度来说,可以不必引入,因为class能做的struct也能做,为什么保留则是因为它所支持的封装和继承的哲学。

C程序巧计有时候却成为C++程序的陷阱。比如C程序中的变长结构体,变长结构体要求把变长数组放在结尾处,但是由于C++中继承和虚函数引入,无法保证该变长数组放置在结尾,从而这种做法在C++中是无法使用的。

C struct在C++中一个合理用途,是当你要传递“一个复杂的class object的全部或部分”到某个C函数中去时,struct声明可以把数据封装起来,并保证拥有与C兼容的空间布局。(还是C++和C兼容问题)

第1.3节 对象的差异

多态只存在于一个个的public class体系中。

 class Book:public Library_materials{...};
 Library_materials thing1;
 Book book;
 thing1=book;//sliced
 thing1.chek_in();
 Library_materials &thing2=book;
 thing2.check_in();

thing1是在编译阶段确定,thing2则是在运行阶段确定,这就是二者对象之间的差异。

class object大小包含3个部分:

1.nonstatic data members总和大小;

2.由于字节对齐要求填补空间;

3.为了支持virtual内部产生(编译器)的任何额外负担。

void* ptr指向一个地址,但是不知道它所含有空间大小,因此不能通过它操作所指object。

ZooAnimal za;
ZooAnimal *pza;

Bear b;
Panda *pp=new Panda;

pza=&b;

继承关系如下图

可能内存布局图如下

一个pointer或一个reference之所以支持多态,是因为并不引发内存中任何“与类型有关的内存委托操作”;会受到改变的只是他们所指向的内存的“大小和内容解释方式”而已。

C++也支持具体的ADT程序风格,被称为OB(object-based)最主要差别是非多态,,所有的函数引发的操作都在编译时期解析完成,不需要virtual机制,有更好的空间紧凑性,速度更快,没有弹性是它的缺点。

设计要在弹性(OO)和效率(OB)之间进行选择

posted @ 2012-06-05 15:24  Raymond东东  阅读(111)  评论(0编辑  收藏  举报