添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
C++初学者实验室
首发于 C++初学者实验室

C++内存模型 (一)多态与继承

今天跑到了上海图书馆,决定把这个事情解决了。

cnblogs.com/QG-whz/p/49


这篇文章,讲的还成。就是太长了,一次性看不完。而且在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() {}