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

    一、前言

      在看了皓哥的C++对象的布局之后:http://blog.csdn.net/haoel/article/details/3081328。感觉自己还是总是不能记得很清楚,故在此总结一下C++对象的内存布局,一遍以后及时复习。

    二、

    1. 单一非虚继承:有成员变量,有虚函数和虚函数的覆盖,不是虚拟继承


    源码如下:

    #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;
        }
        virtual void h()
        {
            cout << "Parent::g()" << endl;
        }
    };
    
    class Child : public Parent
    {
    public:
        int ichild;
        Child() : ichild(100) {}
        virtual void f()
        {
            cout << "Child::f()" << endl;
        }
        virtual void g_child()
        {
            cout << "Child::g_child()" << endl;
        }
        virtual void h_child()
        {
            cout << "Child::h_child()" << endl;
        }
    };
    
    class GrandChild : public Child
    {
    public:
        int igrandchild;
        GrandChild() : igrandchild(1000) {};
        virtual void f()
        {
            cout << "GrandChild::f()" << endl;
        }
        virtual void g_child()
        {
            cout << "GrandChild::g_child()" << endl;
        }
        virtual void h_gradnchild()
        {
            cout << "GrandChild::h_grandchild()" << endl;
        }
    };
    int main(int argc, char **argv)
    {
        GrandChild gc;
        typedef void(*Fun)(void);
        Fun pf;
    
        cout << "[0] GrandChild::vfptr->" << endl;
        cout << "    [0]";
        pf = (Fun)*(int *)*(int *)&gc;
        pf();
    
        cout << "    [1]";
        pf = (Fun)*((int *)*(int *)&gc + 1);
        pf();
    
        cout << "    [2]";
        pf = (Fun)*((int *)*(int *)&gc + 2);
        pf();
    
        cout << "    [3]";
        pf = (Fun)*((int *)*(int *)&gc + 3);
        pf();
    
        cout << "    [4]";
        pf = (Fun)*((int *)*(int *)&gc + 4);
        pf();
    
        cout << "    [5]";
        pf = (Fun)*((int *)*(int *)&gc + 5);
        pf();
    
        cout << "[1] Parent.iparent = " << (int)(*((int *)&gc + 1)) << endl;
        cout << "[2] Child.ichild = " << (int)(*((int *)&gc + 2)) << endl;
        cout << "[3] GrandChild.igrandchild = " << (int)(*((int *)&gc + 3)) << endl;
        return 0;
    }

    代码运行结果如下:

    [0] GrandChild::vfptr->
            [0]GrandChild::f()
            [1]Parent::g()
            [2]Parent::g()
            [3]GrandChild::g_child()
            [4]Child::h_child()
            [5]GrandChild::h_grandchild()
    [1] Parent.iparent = 10
    [2] Child.ichild = 100
    [3] GrandChild.igrandchild = 1000

    由此可见,在这种继承关系下,一个对象会有一个被称作虚函数表指针的vfptr。接着会存放Parent -> Child -> GrandChild。这里直接把皓哥的图片拿来用了:

    可以看出:1.虚函数表指针在整个对象的最前面;

         2.基类数据成员放在派生类的前面;

         3.在虚函数表中派生类覆盖的函数得到了更新。

    sizeof(gc) = 16 : sizeof( vfptr ) + 3 * sizeof( int )

  • 相关阅读:
    MySQL与Navicat的安装及使用教程
    数据结构与算法1
    Spring Cloud Gateway 聚合 Swagger
    Linux上GitLab+Jenkins实现Vue、Spring Cloud项目的自动部署
    JPA and ( or )
    How to autowire RestTemplate using annotations
    MyBatis的解析和运行原理(源码分析)
    MyBatis映射器总结
    什么是泛型?泛型的基本原理与使用优势。
    MyBatis配置总结
  • 原文地址:https://www.cnblogs.com/uangyy/p/4621561.html
Copyright © 2011-2022 走看看