深度探索C++对象模型<二>

关键词带来的困扰

这里需要区分的是struct和class,通常情况下我们认为在C的struct和C++支持的class之间,关键词本身并没有提供了差异。

另外一个需要的注意的问题是,有一些在C中可用的trick,用在C++里可能出现意想不到的问题。例如我希望一个struct有可变的长度

1
2
3
4
5
struct mumble {
char pc[1];
};

struct mumble* p_mumble = (struct mumble* )malloc(sizeof(mumble)+sizeof(string)+1);

但如果是用class来声明,由于多个区域之间的顺序内存布局是不一定的,也就无法这样精细地控制内存。

对象的差异

C++程序设计模型支持三种programming paradigms:

  • prodedural model
  • ADT
  • object-oriented model

需要多大的内存来保存一个class的大小:

  • 其所有nonstatic data members的大小;
  • 由于alignment而需要进行padding的大小,有可能在数据成员上填补,也可能在集合体上进行填补;
  • 为了支持virtual function而带来的额外负担;

指针的类型,例如一个指向对象的指针和一个指向整数的指针,一个指向template array的指针有什么区别?关键不在于指针内容的不同,而是通过指针寻址出来的对象不同,也就是指针类型告诉了编译器应该如何解释特定内存地址的内容和大小。

而一个指针类型为void*的指针,其仅仅代表一个地址,通过转型cast,使得编译器能够解释指出内存的大小和位置。

考虑这种情况:

1
2
3
Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

上面的两个指针都执行了Bear object的第一个字节,但不同的是,pz涵盖的只有Bear object的ZooAnimal部分。而pb则涵盖了整个Bear object;也就是你无法通过pz去使用Bear的任何members。除非使用虚函数机制;

也就是通过pz所指向的类型去调用某个函数,这里的关键是类型信息并不是存储在pz里,而是存储pz所指向的对象的虚指针和虚指针所指向的虚表里。

而如果直接把派生类的对象塞进基类的对象里,派生类对象会被切割,也就是失去了多态的功能,