zoukankan      html  css  js  c++  java
  • 对象内存模型

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

    存放规则:  

      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
  • 相关阅读:
    Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) C. Success Rate
    Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) B. T-Shirt Hunt
    go 读取数据库所有表数据显示到网页(便于测试时看)
    go 文件上传
    go 文件服务(读取须权限)
    vps git无法clone DNS解析错误
    go 自己封的postgresql连接池操作包
    看 迪杰斯特拉(Dijsktra)算法体会
    Floyd算法(弗洛伊德算法) 百度百科
    Constructing Roads In JGShining's Kingdom
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10852395.html
Copyright © 2011-2022 走看看