zoukankan      html  css  js  c++  java
  • C++使用继承时子对象的内存布局

    C++使用继承时子对象的内存布局

     

    C++使用继承时子对象的内存布局

    1 示例程序

    class A
    {
    protected:
        int a;
    public:
        A() : a(1) {}
    
        virtual void a1() {}
        virtual void a2() {}
    };
    
    class B
    {
    protected:
        int b;
    public:
        B() : b(2) {}
    
        virtual void b1() {}
        virtual void b2() {}
    };
    
    class C : public A, public B
    {
    protected:
        int c;
    public:
        C() : c(3) {}
    
        virtual void a1() {}
        virtual void b1() {}
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        C *c = new C;
        B *b = (B *)c;
    
        return 0;
    }
    

    类 A/B/C 之间的关系如下:

    2 对象的内存布局

    C *c = new C();
    

    在上面这段代码中,对象 c 的内存布局如下:

    低地址        
           
    1. 虚表指针 –> &C::a1 &A::a2 .
    2. A::a        
    3. 虚表指针 –> &C::b1 &B::b2 .
    4. B::b        
    5. c::c        
           
    高地址        

    c 对象从低地址到高地址依次存储了:A 的虚表指针、A 的成员变量、B 的虚表指针、B 的成员变量、C 的成员变量。我们发现,虚函数表 A 中的 A::a1 函数被 C::a1 函数覆盖了,虚函数表 B 中 B::b1 函数被 C::b1 覆盖了,这是因为 C 重写了 a1 和 b1方法。这意味着通过 c 对象中的虚表指针调用 a1 或 b1 函数,只能够调用到 C 类中重写的方法。

    C *c = new C;
    c->b1();
    
    B *b = c;
    b->b1();
    

    上面的两句调用都会调用 C 的 b1 方法。另外,在对 b 赋值时,b 得到的结果并不是 c 的值,而是 c+8,这正好是 c 对象中用于存储 B 虚表指针的地址。

    Date: 2016-01-12T22:44+0800

    Author: ruleless

    Org version 7.9.3f with Emacs version 24

    Validate XHTML 1.0
  • 相关阅读:
    c语言字符串_续
    c语言中文件的操作
    Linux基础知识
    netstat
    wireshark 过滤规则
    常用cmd命令
    优化过的redis封装类
    二十三岁,新的起点
    计划看的书目
    [转载]爱上一个给予你正能量的人
  • 原文地址:https://www.cnblogs.com/liuyang1012525/p/5125878.html
Copyright © 2011-2022 走看看