对象内存模型

对象对象模型:对象在内存是如何存放的

存放规则:  

  1. class内存对齐规则和struct相同。

  2. class 成员函数和成员变量分开存放,每个对象有独享的成员变量(堆栈全局数据),同一类的所有对象共享同一成员函数(代码段)。

       3. 调用成员函数时将对象地址传递给成员函数(隐式传递),成员函数通过对象地址(this指针)访问成员变量。 

  4. 对象只包含了成员变量,没有包含成员函数。

#include<iostream>
#include<string>
using namespace std;

class A
{
    int a;            // 堆栈全局段   addr  0x7ffffc6795a0
    int b;            // 堆栈全局段   addr  0x7ffffc6795a4
    char  c;         // 堆栈全局段   addr  0x7ffffc6795a8
    double d;         // 堆栈全局段   addr  0x7ffffc6795b0
public:
    void print()      // 代码段
    {
     cout << "addr of a = " << &a << endl;
     cout << "addr of b = " << &b << endl;
     cout << "addr of c = " << &c << endl;
     cout << "addr of d = " << &d << endl;
    }
};


class B
{
    int a;            
    int b;            
    char c;            
    double d;        
public:
    void print()   
    {
     cout << "addr of a = " << &a << endl;
     cout << "addr of b = " << &b << endl;
     cout << "addr of c = " << &c << endl;
     cout << "addr of d = " << &d << endl;
    }
};


int main(void)
{
    cout << "size of A = " << sizeof(A) << endl;
    A a;
    a.print();
    B* p = reinterpret_cast<B*>(&a);  // 通过地址可以直接访问修改private成员
    p->a = 1;                          // private,protect,public关键字只在编译期有效
    p->b = 2;                          // private,protect,public关键字只在运行期无效
    p->c = 'c';
    p->d = 3;   
    a.print();                         // 对象a的地址被传递到A类的print()函数。
    return 0;
}

继承对象模型:  

  1. 子类继承对象模型时父类成员叠加子类成员得到的。

  2. 父类成员函数在代码段,子类对象成员函数也在代码段  

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int a;
    int b;void print()
    {
        cout << "addr of a = " << &a << endl;  // 0x7ffff70cea14
        cout << "addr of b = " << &b << endl;  // 0x7ffff70cea18
    }
};

class Child: public Parent
{
private:
    int c;
public:
    void print()
    {
        cout << "addr of a = " << &a << endl;  // 0x7ffff70cea1c
        cout << "addr of b = " << &b << endl;  // 0x7ffff70cea20
        cout << "addr of c = " << &c << endl;  // 0x7ffff70cea24
    }
};

int main()
{
    cout << " size of Parent =  " << sizeof(Parent) <<  endl;  // 8
    cout << " size of Child =  " << sizeof(Child) <<  endl;    // 12 父类成员加子类成员
  Parent p;
  Child c;
  p.print();
  c.print();
return 0; }

 多态的对象模型:

 虚函数实现多态的原理:

  1. 编译器为类创建一个虚函数表。

  2. 对象定义一个指针指向虚函数表。

  2. 虚函数表是存储指向虚函数的指针一个数据结构。

  3. virtual 关键字定义的成员 函数会自动放入虚函数表。 

多态调用时:p->vir_func();
p    -->   vptr     -->     vtable   -->  0xff000111
函数调用 --> 虚函数表指针 --> 虚函数表中函数指针  --> 虚函数地址    
#include <iostream>
#include <string>

using namespace std;

class Parent
{
protected:
    int a;
    int b;
public:
    virtual void print()
    {
        cout << "addr of a = " << &a << endl;  //0x7fffdd1934d8
        cout << "addr of b = " << &b << endl;  // 0x7fffdd1934dc
    }
};

class Child : public Parent
{
    int c;
public:  
    void print()   // 通过继承变也成虚函数
    {
        cout << "there should be a address of  virtual_table " <<  endl; //
        cout << "addr of a = " << &a << endl;  //  0x7fffdd1934e8
        cout << "addr of b = " << &b << endl;  //  0x7fffdd1934ec
        cout << "addr of c = " << &c << endl;  //  0x7fffdd1934f0
    }
};

struct Test
{
    void* v_ptr;   // 虚函数表指针
    int a;
    int b;
    int c;
};

int main()
{
    Child c;
    Parent p;
    c.print();
    p.print();
    
    cout << "sizeof(Parent) = " << sizeof(Parent) << endl;        // 16 = 4+4+8        8存放的是虚函数表地址
    cout << "sizeof(Child) = " << sizeof(Child) << endl;          // 24 = 4+4+4+(4)+8  8存放的是虚函数表地址
    
    Test* test_p = reinterpret_cast<Test*>(&c);

    cout << " addr of virtual_table = " << &test_p->v_ptr << endl;   // 0x7fffc0f14390  虚函数表指针存放在对象内存的最开始
    cout << " addr of test.a =  " << &test_p->a << endl;             // 0x7fffc0f14398
    cout << " addr of test.b =  " << &test_p->b << endl;             // 0x7fffc0f1439c
    cout << " addr of test.c =  " << &test_p->c << endl;             // 0x7fffc0f143a0

    return 0;
}

C语言实现多态:

#include "malloc.h"

typedef void Demo;
typedef void Derived;

Demo* Demo_Create(int i, int j);
int Demo_GetI(Demo* pThis);
int Demo_GetJ(Demo* pThis);
int Demo_Add(Demo* pThis, int value);
void Demo_Free(Demo* pThis);

Derived* Derived_Create(int i, int j, int k);
int Derived_GetK(Derived* pThis);
int Derived_Add(Derived* pThis, int value);

static int Demo_Virtual_Add(Demo* pThis, int value);
static int Derived_Virtual_Add(Demo* pThis, int value);

struct VTable     // 2. 定义虚函数表数据结构
{
    int (*pAdd)(void*, int);   // 3. 虚函数表里面存储什么???
};

struct ClassDemo
{
    struct VTable* vptr;     // 1. 定义虚函数表指针  ==》 虚函数表指针类型???
    int mi;
    int mj;
};

struct ClassDerived
{
    struct ClassDemo d;
    int mk;
};

static struct VTable g_Demo_vtbl = 
{
    Demo_Virtual_Add
};

static struct VTable g_Derived_vtbl = 
{
    Derived_Virtual_Add
};

Demo* Demo_Create(int i, int j)
{
    struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo)); 

    if( ret != NULL )
    {
        ret->vptr = &g_Demo_vtbl;   // 4. 关联对象和虚函数表
        ret->mi = i;
        ret->mj = j;
    }
    
    return ret;
}

int Demo_GetI(Demo* pThis)
{
     struct ClassDemo* obj = (struct ClassDemo*)pThis;    

     return obj->mi;
}

int Demo_GetJ(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->mj;
}

// 6. 定义虚函数表中指针所指向的具体函数
static int Demo_Virtual_Add(Demo* pThis, int value)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;
    
    return obj->mi + obj->mj + value;
}


// 5. 分析具体的虚函数!!!!
int Demo_Add(Demo* pThis, int value)
{

    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->vptr->pAdd(pThis, value);
}

void Demo_Free(Demo* pThis)
{
    free(pThis);
}

Derived* Derived_Create(int i, int j, int k)
{
    struct ClassDerived* ret = (struct ClassDerived*)malloc(sizeof(struct ClassDerived));
    
    if( ret != NULL )
    {
        ret->d.vptr = &g_Derived_vtbl;
        ret->d.mi = i;
        ret->d.mj = j;
        ret->mk = k;
    }
    
    return ret;
}

int Derived_GetK(Derived* pThis)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis;
    
    return obj->mk;
}

static int Derived_Virtual_Add(Demo* pThis, int value)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis; 

    return obj->mk + value;
}

int Derived_Add(Derived* pThis, int value)
{   
    struct ClassDerived* obj = (struct ClassDerived*)pThis;
    
    return obj->d.vptr->pAdd(pThis, value);
}
View Code
#include "stdio.h"

typedef void Demo;
typedef void Derived;

Demo* Demo_Create(int i, int j);
int Demo_GetI(Demo* pThis);
int Demo_GetJ(Demo* pThis);
int Demo_Add(Demo* pThis, int value);
void Demo_Free(Demo* pThis);

Derived* Derived_Create(int i, int j, int k);
int Derived_GetK(Derived* pThis);
int Derived_Add(Derived* pThis, int value);

void run(Demo* p, int v)
{
    int r = Demo_Add(p, v);
    
    printf("r = %d
", r);
}

int main()
{
    Demo* pb = Demo_Create(1, 2);
    Derived* pd = Derived_Create(1, 22, 333);
    
    printf("pb->add(3) = %d
", Demo_Add(pb, 3));
    printf("pd->add(3) = %d
", Derived_Add(pd, 3));
    
    run(pb, 3);
    run(pd, 3);
    
    Demo_Free(pb);
    Demo_Free(pd);
    
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zsy12138/p/10852395.html