您的位置:首页 > 移动开发 > Objective-C

Inside The C++ Object Model 学习笔记 -- 关于对象

2014-06-30 09:31 671 查看
一. C/C++ 语言中的方法和数据

1. C语言的数据和方法 语言中数据和处理(函数)是分开的,语言本身不支持数据和函数的关联性。这种方法我们称之为:程序性的;它是由"分布在各个以功能为导向的函数中"d的算法所驱动,它们处理的是共同的数据。

2. C++语言数据和方法

C++中是通过ADT(Abstract Data Type, ADT)来实现的。 C++可以在不同层次上进行抽象,造成的复杂度可能也不一样。

书中从简单到复杂四个层次的抽象: 简单类、继承、一个参数的Template、两个参数的模板。



二.C++加上封装后的布局成本(Layout Costs for Adding Encapsulation)



1. C++中的对象的布局

a. data member: 直接的包涵在每一个class object(注意: 类对象,不是类)之中,这和C struct的情况是一样的

b. member function: 它不出现在class object 之中.

non-inline member: 它会产生一个行数的实体. 如果是非static的funciton, 每个function会加上一个this指针作为function的第一个参数.

inline member: 会在每一个使用者身上产生一个函数的实体。这一般是为了提高效率。

2. C++布局和存取上的额外开销

a. virtual function 机制: 用以支持一个有效的"执行期绑定(runtime binding)"

b. virtual base class



三. C++对象模型(The C++ Object Model)

1. 简单对象模型(A Simple Object Model)

这种模型中,每个object是一系列的slots, 每个slot指向一个member. 每个member按其申明的次序各占用一个slot. 这里的member包括data member 和 function member. 每个member是通过slot的索引来访问的。

具体的模型参看:



2. 表格驱动模型(A Table-driven Object Model)

这种模型中把class object的members分组放在一个data member table 和一个function member table中,class object内含两个指向table的指针. member function table 是一系列的slots, 每个slot指向一个function member. data member table 则是直接的包涵有data本身。

具体的模型参看:



3. C++对象模型(The C++ Object Model)

C++的对象模型如下:

a. nostatic data members 被直接的配置在每一个class object之内。

b. static data member 、static 和 nonstatic function members全部被放在所有的class object 之外。

c. virtual functions 则是以下列步骤支持的:

i. 每一个class 产生一堆指向virtual functions的指针,放在表格之中,我们称这个表格为:virtual table(vtbl).

ii. 每个得class object 被添加了一个指针,指向相关的virtual table,我们把class object的这个指针称之为vptr(virtual pointer);这个vptr的设定和重置是由类的constructor、destructor 和 copy assignment 运算符自动完成的;每个类的type_info object也是经由virtual table指出的,通常是放在表格的第一个slot处。

具体的模型参看:



d. 加上继承(Adding Inheritance)

在 A Simple Object Model 中,每一个基类可以被derived class object的一个slot指出,该slot内含base class subobject的地址。

在虚拟继承的情况下,base class 不管在继承链中被派生多少次,永远只有一个实体(subobject). 书中以iostream继承体系说明。

C++中的base class subobject的data members直接放置于derived class object中。那么它的function members是怎么处理的呢?(我没有理解这块)

对于virtual base class, C++ 2.0 是在class object中添加一个关联 virtual base class object的指针。

e. 对象模型对程序的影响

我觉得书上的这段代码非常好的体现了不同模型对程序的影响

预定义 class X 如下:


class X


{


public :


virtual ~ X() {

}


X & X( const X & rhs) {

}




virtual void foo() {

}


}




// 定义一个方法


X foobar()


{


X xx;


X * px = new X();


//


xx.foo();


px -> foo();




//


delete px;


return xx;


}




// 这个函数可能的转化为:


void foobar(X & _result)


{


_result.X::X();




//


px = new ( sizeof (X) );


if (px != 0 )


px -> X::X();




// 这里是不使用virtual 机制的foo调用


// 注意这里的调用方法,不是用vtbl,


// 这样如果有从class X 继承的类初始化或赋值给X基类时,


// 调用foo的方法是X的方法, 是编译时确定的


foo( & _result);




// 是用virtual 机制的foo调用, 它是运行时确定的


( * px -> vtbl[ 2 ])(px);




// delete px


if (px != 0 )


{


( * px -> vtbl[ 1 ])(px); // destructor


_delete(px);


}




//


return ;







四. 关键词所带来的差异(A Keyword Distinction)


讨论了class 和 struct 的差异和选择

五. 对象的差异( A Object Distinction)

1. C++程序设计模型支持三种programming paradigms.

a. 程序模型(procedural model) 就是像 C 一样进行编程

b. 抽象数据类型模型(abstract data type model, ADT) 用对象进行编程

c. 面向对象模型(object-oriented model)

模型中有一些彼此相关的类型,通过一个抽象的base class被封装起来(也就是:接口)。类型之间的操作是通过接口进行的。

纯粹的以一种paradigm写程序是好的.(哈哈,好像这不太可能,我还做不到)

二. 面向对象模型(object-oriented model)

a . C++中多态支持性的支持是通过: pointer 和 reference来实现的.

多态通过下面三种方法来支持:

i. 经由一组隐含的转化操作: shape *ps = new circle();

ii. 经由virtual function 机制 ps->rotate();

iii. 经由 dynamic_cast和typeid来支持:

if(circle *pc = dynamic_cast<circle*>(ps)) ...

多态内存需求

i. 其 nonstatic data members 的总和大小

ii. 任何字节对齐的额外填充(padding)

iii. 支持virtual 而产生的额外负担

b. 指针的类型

"指向不同类型的各指针"的差异,不在于其指针的表示法不同,也不在于其内容的不同, 而是其寻址出来的object的类型不同。也就是说"指针类型"会教导编译器如何解释某个特定地址中的内存内容及其大小.

c. 加上多态之后(Adding Polymorphism)

以如下为例:

1

class Bear : public ZooAnimal

2

{

3

public :

4

Bear();

5

~ Bear();

6


7

//


8

void rotate();

9

virtual void dance();

10


11

//


12

protected :

13

enum Dances {

} ;

14


15

Dances dances_known;

16

int cell_block;

17

} ;

18


19

///

20

Bear b( " Yogi " );

21

Bear * pb = & b;

22

Bear & rb = * pb;

23


具体的内存布局如



//

现有

1 Bear b;

2 ZooAnimal *pz = &b;

3 Bear *pb = &b;

4

以上每个都指向Bear object的第一个byte,其间的差别是,pb所涵盖的地址包含整个的Bear object, 而pz所涵盖的地址只包含Bear object中的 ZooAnimal subobject部分。你只能用pz来处理Bear中的virtual functions, 而不能直接的处理Bear中的其他任何members.

注意pz的类型将在编译时确定以下两点:

i. pz固定的可用接口

ii. pz的接口的access level;因为子类的access level可能是不同于基类的,编译时会检测是否可以转换。

e. 对象赋值问题


Bear b;


ZooAnimal za = b;




// ZooAnimal::rotate() invoked


za.rotate();





这里有两个问题

i. za为什么调用的是ZoomAnimal::rotate的实体而不是 Bear的实体?

答:za并不是一个Bear, 它只是一个ZoomAnimal, 多态的这种特性不能用在直接存取的objects上。所以 za.rotate()调用只能是 ZooAnimal::rotate()

ii. 如果初始化函数将一个object的内容完全拷贝到另一个object中去,为什么za的vpt不是指向Bear的virtual table呢?

答:编译器在初始化或赋值操作时,如果某个object含有一个或多个vptrs, 那么这些vptrs的内容不会被原对象初始化或改变.

例如上例的 ZooAnimal za = b, 这里的vptr并不会被 b 的vptr所替代.

本文出自:http://blog.csdn.net/jzp_cn/article/details/668125
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: