Lesson 1 关于对象模型

来源:互联网 发布:java开方如何保留小数 编辑:程序博客网 时间:2024/05/04 10:04
        Ojbect是OO系统运行期的基本单元,class则是对系统中繁杂的对象进行分类的方法。在进行类抽象的时候,我们通常要依赖于Reusable准则。从类繁衍的角度来看,表达多种不同行为的对象的方法有:Inheritance和Parameterized Class。这就意味着C++在描述ADT的时候比C语言要复杂,但并不意味这C++没有威力。不过同时更有威力并不意味着更容易使用【引P5】。 
        C++的对象模型(The C++ Object Model)

  首先看一下C++的对象主要包含那些部分。对象主要包含Data和Methods。其中Data分为Static和NonStatic两类;Methods分为Static、NonStatic和Virtual三类。Stroustrup(牛人啊)是这样设计的:NonStatic Data放在每一个对象中;Static Data、Static Methods和NonStatic Methods放在对象之外,只有一份。而对于Virtual Methods则稍微麻烦些。第一,为每个类对象构造一张表,称为VTable,也就是个(void*)的数组,里面用来放地址。第二,为每个对象增加一个指向VTable的指针,称为VPTR。第三,这个VPTR的设定和改变由Constructor、Destructor和Copy Assignment来操作;第四,VTable的第一项一定是关于这个类的RTTI信息。

  这样,一个简单的没有继承层次的对象内存布局类似于: [_data(4B)|vptr(4B)] + s_a(4B) + Foo(4B) + Instance(4B) = 20B。

class A 

private

        
int
 _data;
       
static A*
 s_a;
public

        
void
 Foo();
  
static void
 Instance();
}
;
         对于单继承甚至多继承怎么处理呢? 来看下面一个层次结构:
     class Base { ...... };

  class A : virtual Base { ...... };

  class B : virtual Base { ...... };

  class D : A, B { ...... };

  为了处理继承,我们为一个派生类引入一个基类列表,用来枚举基类对象的内存信息。在派生类中增加一个指向这个基类列表的指针,称为BPTR。这样就可以通过BPTR来找到基类的对象信息。上述层次的内存变成了这个样子:

  class Base{ ...... };

  class A { _bptr; ......; _vptr; };

  class B { _bptr; ......; _vptr; };

  class D { _bptr; ......; _vptr; }

  而这个D::_bptr则指向这样一个基类列表: [A的对象地址|B的对象地址]。

  在这一章中,书中花了几篇的地方来讲解C++中的Struct的存在及原因。归纳如下:最主要的是向C兼容;但是引入Struct后,却产生了大量的问题。但是C++编译器都遵循兼容的准则把这些问题解决了,从而增加了C++的语法多样性。我个人认为,如果采用OO Paradigm就不要使用struct。有的类库,比如MFC都认为如果要表现一种简单值集合的观念,就用Struct。我不反对,你可以根据自己的习惯采纳。因为现代的编译器都会给出UI提示,你能在复用一个类型的时候知道它是Class还是Struct(无论怎样编译器都兼容这个问题)。 其实在DotNET CLR中的值类型和引用类型的分类倒是能够很好的解释C++中的Struct和Class在语义上的区别。

原创粉丝点击