深度探索C++对象模型第一章关于对象

著:Stanley B. Lippman  侯捷译  Inside the C++ Object Model

第一章:关于对象(Object Lessons)

C++对象模型,了解到也是一个演变的过程,C++对象中包含了以下内容:(data members) non-static data,static data(const),以及(member functions):static,non-static,virtual

发展的主要过程主要集中于如何存储data 和 function,寻求时间和空间的最高效;

第一种模型 简单对象模型,A Simple Object Model

把所有的data和function的地址存储在class中(即都是pointer-to-member),相对比较灵活,class大小固定,间接引用;但由于间接引用会带来访问时间开销;

而object生成中只需要指向base class即可,并对相应数据指针覆盖即可; (总结:把所有的data和function都以virtual的形式间接访问,缺点data对象带来访问开销)

第二种模型:表格驱动对象模型 A Table-driven Object Model

在第一种模型基础上改进,将data member和function member放到独立的table中,这样在class中仅需要保存两个ptr即可,减少了空间。没有实际应用,但member function table被应用virtual functions设计中;

第三种: C++对象模型  The C++ Object Model

吸收上两种模型的精华,对内存空间和存取时间做了优化,对class中各种类型进行了差异性处理。分别如下:object中仅存储non-static data和一个vptr指针,该指针指向一个vtable(包含所有的虚拟函数指针), static-data 和 function 独立于对象存在。

可以支持单继承和多重继承,virtual可以在多重继承中共享继承,仅保留父类的一份对象空间。

优势:data member通过直接访问,提高访问时间

缺点: base class members的任何改变,都会影响到derived class members。

1.2 关键词带来的差异

主要struct和class的不同会给C程序员转到C++程序员带来一些困惑,到C++开发中,struct类型和class类型基本一致,仅在访问权限方面不同,struct默认为public,而class默认为private。初次之外,class可以用于template声明,作用和typename一致,而struct无法应用。

C++中数据内存布局

另外在C++中数据每个access section数据存储位置和声明顺序一致,而不同的access section在内存中顺序不一致;

1.3 对象的差异性

1) 指针的不同

指针之间没有不同,关键是根据指针的类型得到所指向的内存空间的不同。如int *指向整数布局空间(一般4个bytes),而char *,则仅指向一个byte的字节空间,object * 指向object的内存布局空间。 void * 只能表示一个地址,而不能通过它来操作一个object。

2)用指针和引用来实现多态

隐形的转换成基类指针 -> 调用虚拟函数 -> dynamic_cast<derived object *>  动态判断类型来实现多态

3)class object的内存

主要包含nonstatic data  , alignment bytes, virtual mechanism 所带来的消耗

4)绑定和多态

编译期间:编辑器就将非引用和指针的访问以静态的方式进行绑定,然后运行期间执行;而引用和指针则需要查看是否连接到虚拟函数,然后在运行期间查找特定的函数;

基类的指针只能够访问到基类access section内的member,而无法访问到子类的member(除非实现virtual)

5)OO和OB (object-oriented 和 objected-based) 

前者是面向对象设计,提供了继承和多态(弹性),而后者是基于对象设计,不提供继承,则内容紧凑,消耗空间较少(如String class)(效率)

实例:

  1. #include<iostream>
  2. using namespace std; 
  3. template <class T>
  4. struct Node{
  5.     T a;
  6. };
  7. class A {
  8.     public:
  9.         A(){
  10.         cout<<"a1"<<endl;
  11.         }
  12.         A(const A&a){
  13.           cout<<"a2"<<endl;
  14.         }
  15.         int a;
  16.         virtual void  out(){
  17.          cout<<"A"<<endl;
  18.         }
  19. };
  20. class B:public A{
  21.  public :
  22.      int b;
  23.      B(){
  24.         cout<<"B1"<<endl;
  25.      }
  26.      void out(){
  27.         cout<<"B"<<endl;
  28.      }
  29. };
  30. int main(){
  31.     B b;
  32.     A a = b;  //将b强行转换为a,b会进行裁剪,然后重新生成a,调用了A的拷贝构造函数,另外新生成的a中的vptr仍然指向A的vtable
  33.     a.out();  //由于a不是指针或者引用,所有在编译期间已经实现了静态绑定,绑定了A中的out函数。而如果是pointer,则会绑定为(*a->vptr[index])()
  34.     return 0;
  35. }

一个pointer或一个reference之所以支持多态,是因为它们并不引发内存中任何“与类型有关的内存委托操作”(type-dependent commitment),会受到改变的,只是它们所指向的内存的“大小和内容解释方式”而已。

posted @ 2014-07-21 11:22  purejade  阅读(180)  评论(0编辑  收藏  举报