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

一. 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的索引来访问的。
    具体的模型参看: 
    1.1 Simple Object Model.JPG

    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本身。
    具体的模型参看: 
    1.2 Member Table Object Model.JPG

    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处。
    具体的模型参看: 
    1.3 C++ Object Model.JPG 

    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.5 Layout of Object and Pointer of Derived Class.JPG

    // 
    现有   

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值