C++内存模型 (一)多态与继承
今天跑到了上海图书馆,决定把这个事情解决了。
http://www. cnblogs.com/QG-whz/p/49 09359.html
这篇文章,讲的还成。就是太长了,一次性看不完。而且在Apple LLVM version 8.1.0 (clang-802.0.42)下会抛异常。所以我打算先完全听信他的实验结果。
以下是一些总结:
1,对象模型概述
C++一共有2种数据成员,3种函数成员:
我们来做一个包含所有情况的类:
class Base {
private:
int baseI;
static int baseS;
public:
Base(int i) :baseI(i){};
int getI(){ return baseI; }
static void countI(){};
virtual ~Base(){}
virtual void print(void){ std::cout << "Base::print()"; }
2,当世界上没有继承
之后,文章讨论了三种、当
没有继承
这件事情的时候,可能的内存模型:
1,所有的成员都是指针。这样就把所有的成员都统一化,数据、函数,都是一样的。但这样效率很低,没有被采用。
2,表格驱动模型:每个类对象都是2个指针大小,分别指向2张表,一张存放数据,另一张存放函数的指针(而非函数本身)。这个效率更低,没有被采用。
3,C++对象模型:static的数据成员、函数成员,均不放在对象里。nonstatic的数据成员放在对象里。而对于virtual 函数,则通过虚函数表+虚指针来支持。(这里说的对象,相当于Java里的一个对象)。每个对象有一个虚表,按照声明的顺序放置虚函数的指针。同时,也有一个虚表的指针,它的位置为编译器决定——传统上它被放在所有显示声明的成员之后,不过现在许多编译器把vptr放在一个类对象的最前端。
(这里仅适用于没有继承的情况)
之后博主在VS上做了实验,结果如下:
可以看到那个_vfptr,确实包含了声明的2个virtual函数。
之后还有一些别的实验,我做不了,感觉意义也不大,各位有兴趣可以看完以后再去看。
3,世界上有了简单的单继承
class Derive : public Base {
public:
Derive(int d) : Base(1000), DeriveI(d) {};
//overwrite父类虚函数
virtual void print(void) { std::cout << "Drive::Drive_print()"; }
// Derive声明的新的虚函数
virtual void Drive_print() { std::cout << "Drive::Drive_print()"; }
virtual ~Derive() {}
private:
int DeriveI;
有了一个类,继承了Base类。它重载了父类的一个虚函数,同时自己定义了一个新的虚函数。而且也有一个新的数据成员。
那么怎么存储呢。
1,简单模型:加一个指针,指向父类
2,表格驱动模型:每个对象多一个指针,指向父类表(哪张表?没说)
3,C++驱动模型:首先子类父类会各有一张虚函数表,子类的表与父类的表相似,但会覆盖其中override的函数。
//overwrite父类虚函数
virtual void print(void) { std::cout << "Drive::Drive_print()"; }
virtual ~Derive() {}