设为首页 加入收藏

TOP

1.3 对象的差异(An Object Distinction)(3)
2013-10-07 14:48:57 来源: 作者: 【 】 浏览:70
Tags:1.3 对象 差异 Object Distinction

1.3  对象的差异(An Object Distinction)(3)

其中的class object za和指针pza的可能布局如图1.4所示。我将在第3章再回到"data members的布局"这个主题上。

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

但是,一个指向ZooAnimal的指针是如何地与一个指向整数的指针或一个指向template Array(如下,与一个String一并产生)的指针有所不同呢?

  1. ZooAnimal *px;  
  2. int *pi;  
  3. Array< String > *pta; 

以内存需求的观点来说,没有什么不同!它们三个都需要有足够的内存来放置一个机器地址(通常是个word,译注)。"指向不同类型之各指针"间的差异,既不在其指针表示法不同,也不在其内容(代表一个地址)不同,而是在其所寻址出来的object类型不同。也就是说,"指针类型"会教导编译器如何解释某个特定地址中的内存内容及其大小:

译注:Lippman视"不同机器上的word为可变大小,int则固定是16-bits",但另有一种说法是,"不同机器上的int为可变大小,word固定为16-bits",不可不察!

一个指向地址1000的整数指针,在32位机器上,将涵盖地址空间1000~1003(译注:因为32位机器上的整数是4-bytes)。

如果String是传统的8-bytes(包括一个4-bytes的字符指针和一个用来表示字符串长度的整数),那么一个ZooAnimal指针将横跨地址空间1000~1015(译注:4+8+4,如图1.4所示)。

 
图1.4  独立(非派生)class的object布局和pointer布局

嗯,那么,一个指向地址1000而类型为void*的指针,将涵盖怎样的地址空间呢?是的,我们不知道!这就是为什么一个类型为void*的指针只能够持有一个地址,而不能够通过它操作所指之object的缘故。

所以,转换(cast)其实是一种编译器指令。大部分情况下它并不改变一个指针所含的真正地址,它只影响"被指出之内存的大小和其内容"的解释方式。

加上多态之后(Adding Polymorphism)

现在,让我们定义一个Bear,作为一种ZooAnimal。当然,经由"public继承"可以完成这项任务:

  1. class Bear : public ZooAnimal {  
  2. public:  
  3.    Bear();  
  4.    ~Bear();  
  5.    // ...  
  6.    void rotate();  
  7.    virtual void dance();  
  8.    // ...  
  9. protected:  
  10.    enum  Dances { ... };  
  11.  
  12.    Dances dances_known;  
  13.    int cell_block;  
  14. };  
  15.  
  16. Bear b( "Yogi" );  
  17. Bear *pb = &b;  
  18. Bear &rb = *pb; 

b、pb、rb会有怎样的内存需求呢?不管是pointer或reference都只需要一个word的空间(在32位机器上是4-bytes)。Bear object需要24 bytes,也就是ZooAnimal的16 bytes加上Bear所带来的8 bytes。图1.5展示了可能的内存布局。
 
图1.5  Derived class的object和pointer布局
好,假设我们的Bear object放在地址1000处,一个Bear指针和一个ZooAnimal指针有什么不同?
  1. Bear b;  
  2. ZooAnimal *pz = &b;  
  3. Bear *pb = &b; 

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

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

  1. // 不合法:cell_block不是ZooAnimal的一个member,  
  2. // 虽然我们知道pz目前指向一个 Bear object。  
  3. pz->cell_block;  
  4.  
  5. // ok: 经过一个显式的downcast操作就没有问题!  
  6. (static_cast< Bear>( pz ))->cell_block;  
  7.  
  8. // 下面这样更好,但它是一个run-time operation(译注:成本较高)  
  9. if ( Bear* pb2 = dynamic_cast< Bear>( pz ))  
  10.    pb2->cell_block;  
  11.  
  12. // ok: 因为cell_block是Bear的一个member。  
  13. pb->cell_block; 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇1.2 关键词所带来的差异(A Keywo.. 下一篇1.3 对象的差异(An Object Disti..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: