Inside the C++ Object Model 第一讲: 关于对象

在C语言中,我们如果想声明一个struct Point3d,像这样:

typedef struct Point3d{
    float x;
    float y;
    float z;
}Point3d;

某个点特定的坐标可以直接存取,如:

Point3d pt;
pt.x=0.0;

在C++中,Point3d有可能采用独立的”抽象数据类型(abstract data type, ADT)”来实现:

class Point3d
{
public:
    Point3d(float x=0.0, float y=0.0, float x=0.0):
            _x(x), _y(y), _z(z){ }
    float x() {return _x;}
    float y() {return _y;}
    float x() {return _z;}
    void x(float xval) { _x=xval; }
    // ... etc ...
private:
    float _x;
    float _y;
    float _z;       
};

加上封装后的布局成本
C++对Point3d进行封装后,那么布局成本增加了吗?增加了多少?答案是class Point3d并没有增加成本.
class Point3d中三个数据成员_x,_y,_z直接内含在class object(也就是Point3d的对象)之中,就像C struct的情况一样.而成员函数含在class的声明之内,却不出现在object之中.每个non-inline member function只会产生一个函数实例,而inline function则会在其每个使用者身上产生一个函数实例. Point3d支持封装性质,这一点并未给它带来任何空间或执行期的不良后果.实际上,C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括:
● virtual function机制: 用以支持”执行期绑定” (runtime binding)
● virtual base class: 用以实现”多次出现在继承体系中的base class有一个单一而被共享的实例”.
此外,还有一些多重继承下的额外负担,发生在”一个derived class和其第二或后继之base class的转换”之间.一般而言,并不能说C++程序一定比C庞大或缓慢.

1.1 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之外.
这里,英文版原文是这样说的: Nonstatic data members are allocated directly within each class object. Static data members are stored outside the individual class object. Static and nonstatic function members are also hoisted outside the class object.
而virtual functions则以两个步骤支持:
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.
前面声明的class Point的C++对象模型,如图1.3.
这个模型的主要优点在于它的空间和存取时间的效率,主要缺点是如果应用程序代码本身并未改变,但所用到的class objects的nonstatic data members有所修改(如增加,移除或更改),那么应用程序代码同样得重新编译.

这里写图片描述

图1.3中pt是一个class Point的对象,对象中包含nonstatic的数据成员以及一个vptr,指向class Point的virtual table.

1.3 对象的差异(An Object Distinction)

C++程序设计模型支持三种programming paradigms(程序设计范式):
1.程序模型(procedural model): 类似于C,如:
char boy[] = “Danny”;
char pson[10];
strcpy(pson,boy);
2.抽象数据类型模型(abstract data type model, ADT),如:
String girl=”Anna”;
String daughter;
Daughter=girl;
3.面向对象模型(object-oriented model):在此模型中有一些彼此相关的类型,通过一个抽象的base class(用以提供共同接口)被封装起来.(其实就是多态).
在OO paradigm中,只有通过pointers和references才能支持多态,被指定的object的真实类型在每一个特定执行点之前是无法解析的.而在ADT paradigms中,程序员处理的是一个用于固定且类型单一的实例,它在编译时期就已经完全定义好了.

C++以下列方法支持多态:
1.经由一组隐式的转化操作.例如,把一个derived class指针转化为一个指向其public base type的指针:

shape *ps = new circle();

2.经由virtual function机制:

ps->rotate();

3.经由dynamic_cast和typeid运算符:

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

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

一个class object需要多少内存?一般要有:
● 其nonstatic data members的总和大小
● 加上任何由于alignment的需求而填补上去的空间
注解:alignment就是将数值调整到整数的倍数,在32位计算机上,通常alignment为4bytes(32位)
● 加上为了支持virtual而由内部产生的任何额外负担.

指针的类型(The Type of a Pointer):

class ZooAnimal {
public:
    ZooAnimal();
    virtual ~ZooAnimal();
    // ...
    virtual void rotate();
protected:
    int loc;
    String name;
};

ZooAnimal za( "Zoey" );
ZooAnimal *pza = &za;

如果String是传统的8-bytes(包括一个4-bytes的字符指针和一个用来表示字符串长度的整数),那么ZooAnimal的对象za和其指针pza的内存布局可能如图1.4,一个ZooAnimal指针将横跨地址空间1000~1015。
这里写图片描述

而假设指向地址1000的指针为void*呢,它将涵盖怎样的地址空间?答案是不知道。这就是为什么一个类型为void*的指针只能够持有一个地址,而不能通过它操作所指向的object的原因。

加上多态之后(Adding Polymorphism)
定义一个class Bear,派生自ZooAnimal

class Bear : public ZooAnimal {
public:
    Bear();
    ~Bear();
    // ...
    void rotate();
    virtual void dance();
    // ...
    protected:
    enum Dances { ... };
    Dances dances_known;
    int cell_block;
};

Bear b( "Yogi" );
Bear *pb = &b;
Bear &rb = *pb;

B,pb,rb会有怎么样的内存需求?不管是pointer或reference都只有一个word的内存空间(在32位机器上是4-bytes)。Bear object需要24 bytes,也就是ZooAnimal的16 bytes加上Bear带来的8 bytes。
可能的内存布局如图1.5.
这里写图片描述

那么一个Bear指针和一个ZooAnimal指针有什么不同?
Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

它们每个都指向Bear object的第一个byte。差别是 pb所涵盖的地址包含整个Bear object, 而pz所涵盖的地址只包含Bear object中的ZooAnimal subobject.

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

下面一组定义:

{
ZooAnimal za;
ZooAnimal *pza;
Bear b;
Panda *pp = new Panda;
pza = &b;
}

其可能的内存布局如下:

这里写图片描述

当一个base class object被直接初始化为(或是被指定为)一个derived class object时, derived object就会被切割(sliced)以塞入较小的base type内存中。这时候内存中将没有derived class object的布局,多态不再起作用。
C++通过class的pointers和references来支持多态,这种程序设计风格就成为”面向对象”。
C++也支持ADT程序设计风格,如今被称为object-based(OB),如String class,一种非多态的数据实现。一个OB设计可能比对等的OO设计速度更快且空间更紧凑。速度快是因为所有的函数调用操作都是在编译时期完成的,对象构建起来时不需要设置virtual机制。空间紧凑则是因为每一个class object不需要负担传统上为了支持virtual机制而需要的额外符合。不过OB设计比较没有弹性。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Inside the C++ Object Model focuses on the underlying mechanisms that support object-oriented programming within C++: constructor semantics, temporary generation, support for encapsulation, inheritance, and "the virtuals"--virtual functions and virtual inheritance. This book shows how your understanding the underlying implementation models can help you code more efficiently and with greater confidence. Lippman dispells the misinformation and myths about the overhead and complexity associated with C++, while pointing out areas in which costs and trade offs, sometimes hidden, do exist. He then explains how the various implementation models arose, points out areas in which they are likely to evolve, and why they are what they are. He covers the semantic implications of the C++ object model and how that model affects your programs. Highlights *Explores the program behavior implicit in the C++ Object Model's support of object-oriented programming. *Explains the basic implementation of the object-oriented features and the trade offs implicit in those features. *Examines the impact on performance in terms of program transformation.* Provides abundant program examples, diagrams, and performance measurements to relate object-oriented concepts to the underlying object model. If you are a C++ programmer who desires a fuller understanding of what is going on "under the hood," then Inside the C++ Object Model is for you! Get a value-added service! Try out all the examples from this book at www.codesaw.com. CodeSaw is a free online learning tool that allows you to experiment with live code from your book right in your browser.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值