zoukankan      html  css  js  c++  java
  • C++对象内存布局 (二)

    在上一篇文章中讨论了C++单一一般继承的对象内存布局http://www.cnblogs.com/uangyy/p/4621561.html

    接下来继续讨论第二种情况:

    2.单一的虚拟继承:有成员变量,有虚函数和虚函数的覆盖,虚拟继承。

    我们假设下面这样一种继承关系

    源码如下:

    #include <iostream>
    using namespace std;
    
    class Parent
    {
    public:
        int iparent;
        Parent() : iparent(10) {}
        virtual void f()
        {
            cout << "Parent::f()" << endl;
        }
        virtual void g()
        {
            cout << "Parent::g()" << endl;
        }
    };
    
    class Child : virtual public Parent
    {
    public:
        int ichild;
        Child() : ichild(100) {}
        virtual void f()
        {
            cout << "Child::f()" << endl;
        }
        virtual void g_child()
        {
            cout << "Child::g_child()" << endl;
        }
    };
    int main(int argc, char **argv)
    {
        Child c;
        typedef void(*Fun)(void);
        Fun pf;
        
        cout << "[0] Child::vfptr->" << endl;
        cout << "    [0] ";
        pf = (Fun)*((int *)*(int *)&c + 0);
        pf();
    
        cout << "    [0] 0x" << (Fun)*((int *)*(int *)&c + 1) << endl;
    
        cout << "[1] Child::vbptr->" << endl;
        cout << "    [0] " << *((int *)*((int *)&c + 1) + 0) << endl;
    
        cout << "    [1] " << *((int *)*((int *)&c + 1) + 1) << endl;
    
        cout << "    [2] " << *((int *)*((int *)&c + 1) + 2) << endl;
    
        cout << "[2] Child.ichild = " << (int)*((int *)&c + 2) << endl;
    
        cout << "[3] = 0x" << (int *)*((int *)&c + 3) << endl;
    
        cout << "[4] Parent::vfptr->" << endl;
        cout << "    [0] ";
        pf = (Fun)*((int *)*((int *)&c + 4) + 0);
        pf();
    
        cout << "    [1] ";
        pf = (Fun)*((int *)*((int *)&c + 4) + 1);
        pf();
        
        cout << "    [2] 0x" << (Fun)*((int *)*((int *)&c +4) + 2) << endl;
    
        cout << "[5] Parent.iparent = " << (int)*((int *)&c + 5) << endl;
        return 0;
    }

    代码运行结果如下:

    [0] Child::vfptr->
            [0] Child::g_child()
            [0] 0x00000000
    [1] Child::vbptr->
            [0] -4
            [1] 12
            [2] 0
    [2] Child.ichild = 100
    [3] = 0x00000000
    [4] Parent::vfptr->
            [0] Child::f()
            [1] Parent::g()
            [2] 0x00000000
    [5] Parent.iparent = 10

    下面是该对象的内存布局图:

    由上图我们可以知道:

      1.在虚拟继承关系下,派生类的对象会产生一个名为虚基类表指针的指针vbptr,里面存放的是基类在对象中的偏移地址(从1开始,0单元存放的不知道有什么用)

      2.在这种关系先,被继承的基类放在最后面,首先放的是派生类的成员变量和虚函数表

      3.存放的顺序为:派生类虚函数表指针 -> 虚基类表指针 -> 派生类的成员变量 -> NULL -> 基类虚函数表指针 -> 基类成员变量

     

    sizeof(c) = 24 : 2 * sizeof(vfptr) + 2 * sizeof(int) + sizeof(vbptr) + sizeof(void *)

    注意:1.在虚拟机城的继承关系下,派生类的对象会有一个虚基类表指针,占用4个字节;

            2.在派生类和被虚拟继承的基类之间有一个空指针。

  • 相关阅读:
    node.js 安装后怎么打开 node.js 命令框
    thinkPHP5 where多条件查询
    网站title中的图标
    第一次写博客
    Solution to copy paste not working in Remote Desktop
    The operation could not be completed. (Microsoft.Dynamics.BusinessConnectorNet)
    The package failed to load due to error 0xC0011008
    VS2013常用快捷键
    微软Dynamics AX的三层架构
    怎样在TFS(Team Foundation Server)中链接团队项目
  • 原文地址:https://www.cnblogs.com/uangyy/p/4623320.html
Copyright © 2011-2022 走看看