`
xitong
  • 浏览: 6187844 次
文章分类
社区版块
存档分类
最新评论

《深度探索C++对象模型》读书笔记(1)

 
阅读更多

《深度探索C++对象模型》读书笔记(1)。

  在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;
};

   在Stroustrup当初设计的C++对象模型中,Nonstatic data members被配置于每一个class object之内,static data members则被存放在所有的class object之外。Static和nonstatic function members也被放在所有的class object之外,Virtual functions则以两个步骤支持之:

   (1)每一个class产生出一堆指向virtual functions的指针,放在表格之中,这个表格被称为virtual table(vtbl)。

   (2)每一个class object被添加了一个指针,指向相关的virtual table.通常这个指针被称为vptr.vptr的设定(setting)和重置(resetting)都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用以支持runtime type identification,RTTI)也经由virtual table被指出来,通常是放在表格的第一个slot处。

《深度探索C++对象模型》读书笔记(1)

   ***虚拟继承***

   继承关系也可以指定为虚拟(virtual,也就是共享的意思):

 class istream : virtual public ios ...{ ... };
class ostream : virtual public ios ...{ ... };
class iostream : public istream,public ostream ...{ ... };

关键字: malloc wxWidgets OpenGL 多态性 doxygen

《深度探索C++对象模型》读书笔记(1)。

   在虚拟继承的情况下,base class不管在继承串链中被派生(derived)多少次,永远只会存在一个实体(称为subobject)。例如iostream之中就只有virtual ios base class的一个实体。

   ***指针的类型***

   下面有一个ZooAnimal声明:

 class ZooAnimal ...{
public:
ZooAnimal();
virtual ~ZooAnimal();

// ...
virtual void rotate();

protected:
int loc;
String name;
};

   一个指向类的指针与一个指向整数的指针或一个指向template Array的指针之间的差异既不在其指针表示法不同,也不在于其内容(代表一个地址)不同,而是在其所寻址出来的object类型不同。也就是说,“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小:

   1.一个指向地址1000的整数指针,在32位机器上,将涵盖地址空间1000~1003.

   2.如果String是传统的8-bytes(包括一个4-bytes的字符指针和一个用来表示字符串长度的整数),再加上指向vtbl的指针vptr,那么一个ZooAnimal指针将横跨地址空间1000~1015(4+8+4)。

   假设Bear继承于ZooAnimal,如下所示:

 Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

   一个Bear指针和一个ZooAnimal指针虽然都指向Bear Object的第一个byte,但pb所涵盖的地址包含整个Bear Object,而pz所涵盖的地址只包括Bear Object中的ZooAnimal subobject.

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

 // 不合法:cell_block不是ZooAnimal的一个member
// 虽然我们知道pz当前指向一个Bear object
pz->cell_block;

// ok: 经过一个明白的downcast操作就没有问题!
((Bear*)pz)->cell_block;

// 下面这样更好,但它是一个run-time operation(成本较高)
if(Bear* pb2 = dynamic_cast<Bear*>(pz))
pb2->cell_block;

// ok: 因为cell_block是Bear的一个member
pb->cell_block;

关键字: malloc wxWidgets OpenGL 多态性 doxygen

《深度探索C++对象模型》读书笔记(1)。

   ***切割引起的编译器仲裁***

 Bear b;
ZooAnimal za = b;  // 这会引起切割(sliced)
// 调用 ZooAnimal::rotate()
za.rotate();

   为什么rotate所调用的是ZooAnimal实体而不是Bear实体?此外,如果初始化函数(应用于上述assignment操作发生时)将一个object内容完整拷贝到另一个object中去,为什么za的vptr不指向Bear的virtual table?

   第二个问题的答案是,编译器在(1)初始化及(2)指定(assignment)操作之间做出了仲裁。编译器必须确保如果某个object含有一个或一个以上的vptrs,那些vptrs的内容不会被base class object初始化或改变。

   至于第一个问题的答案是:za并不是(而且绝对不会是)一个Bear,它是(并且只能是)一个ZooAnimal.多态所造成的“一个以上的类型”的潜在力量,并不能够实际发挥在“直接存取objects”这件事情上。

   ***面对对象(OO)和基于对象(OB)***

   基于对象的数据类型可以展示封装的非多态形式,但是不支持类型的扩充。一个OB设计可能比一个对等的OO设计速度更快而且空间更紧凑。速度快是因为所有的函数引发操作都在编译时期解析完成,对象建构起来时不需要设置virtual机制;空间紧凑则是因为每一个class object不需要负担传统上为了支持virtual机制而需要的额外符合。不过,OB设计比较没有弹性。

  系列文章:

  《深度探索C++对象模型》读书笔记(2)

  《深度探索C++对象模型》读书笔记(3)

  《深度探索C++对象模型》读书笔记(4)

  《深度探索C++对象模型》读书笔记(5)

  《深度探索C++对象模型》读书笔记(6)

  《深度探索C++对象模型》读书笔记(7)

  《深度探索C++对象模型》读书笔记 最后一记

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics