C++对象成员函数存储示例


本文主要以示例说明C++对象成员函数的存储布局,有关理论知识,请参考Fuction语意学

一、成员函数

1.1、无继承

#include <iostream>
using namespace std;

class X
{
public:
    int a = 0;
    int b = 1;
    virtual void f1() { cout << "X::f1()" << endl; }
    virtual void f2() { cout << "X::f2()" << endl; }
    virtual void f3() { cout << "X::f3()" << endl; }
};

int main()
{
    X x;
    cout << "X:" << endl;
    cout << "sizeof(X) = " << sizeof(X) << endl;
    cout << "vptr address: " << (&x) << endl;
    cout << "x.a address: " << &x.a << endl;
    cout << "x.b address: " << &x.b << endl;

    using f = void (*)();
    f fun = reinterpret_cast<f>(*(int*)(&x));
    f t1 = reinterpret_cast<f>(((int*)fun)[0]);
    f t2 = reinterpret_cast<f>(((int*)fun)[1]);
    f t3 = reinterpret_cast<f>(((int*)fun)[2]);
    t1();
    t2();
    t3();

    return 0;
}

运行时的内存结果如下:
在这里插入图片描述
程序运行结果如下:
在这里插入图片描述
x的内存布局如下所示:
在这里插入图片描述
在这里插入图片描述

1.2、单一继承

#include <iostream>
using namespace std;

class X
{
public:
    int a = 0;
    int b = 1;
    virtual void f1() { cout << "X::f1()" << endl; }
    virtual void f2() { cout << "X::f2()" << endl; }
    virtual void f3() { cout << "X::f3()" << endl; }
};

class Y : public X
{
};

class Z : public X
{
    void f1() { cout << "Z::f1()" << endl; }
    void f2() { cout << "Z::f2()" << endl; }
};

int main()
{
    X x;
    cout << "X:" << endl;
    cout << "sizeof(X) = " << sizeof(X) << endl;
    cout << "vptr address: " << (&x) << endl;
    cout << "x.a address: " << &x.a << endl;
    cout << "x.b address: " << &x.b << endl;

    Y y;
    cout << "Y:" << endl;
    cout << "sizeof(Y) = " << sizeof(Y) << endl;
    cout << "vptr address: " << (&y) << endl;
    cout << "y.a address: " << &y.a << endl;
    cout << "y.b address: " << &y.b << endl;

    Z z;
    cout << "Z:" << endl;
    cout << "sizeof(Z) = " << sizeof(Z) << endl;
    cout << "vptr address: " << (&z) << endl;
    cout << "z.a address: " << &z.a << endl;
    cout << "z.b address: " << &z.b << endl;


    using f = void (*)();
    f funx = reinterpret_cast<f>(*(int*)(&x));

    f x1 = reinterpret_cast<f>(((int*)funx)[0]);
    f x2 = reinterpret_cast<f>(((int*)funx)[1]);
    f x3 = reinterpret_cast<f>(((int*)funx)[2]);
    x1();
    x2();
    x3();

    f funy = reinterpret_cast<f>(*(int*)(&y));

    f y1 = reinterpret_cast<f>(((int*)funy)[0]);
    f y2 = reinterpret_cast<f>(((int*)funy)[1]);
    f y3 = reinterpret_cast<f>(((int*)funy)[2]);
    y1();
    y2();
    y3();

    f funz = reinterpret_cast<f>(*(int*)(&z));

    f z1 = reinterpret_cast<f>(((int*)funz)[0]);
    f z2 = reinterpret_cast<f>(((int*)funz)[1]);
    f z3 = reinterpret_cast<f>(((int*)funz)[2]);
    z1();
    z2();
    z3();

    return 0;
}

其中,Y没有覆盖X的虚函数,因此Y的对象中虚函数的地址与X中虚函数的地址相同,都指向X中的虚函数;Z中覆盖了f1()、f2(),没有覆盖f3(),因此,Z的对象中f1()和f2()的地址与X中的f1()和f2()的地址不相同,分别指向X和Z中的虚函数;而f3()的地址相同,都指向X中的虚函数。

运行时的内存结果如下:
在这里插入图片描述
程序运行结果如下:
在这里插入图片描述
x、y、z的内存布局如下:
在这里插入图片描述

在这里插入图片描述

1.3、多重继承

#include <iostream>
using namespace std;

class X
{
public:
    int a = 0;
    int b = 1;
    virtual void fx1() { cout << "X::fx1()" << endl; }
    virtual void fx2() { cout << "X::fx2()" << endl; }
};

class Y
{
public:
    virtual void fy1() { cout << "Y::fy1()" << endl; }
    virtual void fy2() { cout << "Y::fy2()" << endl; }
};

class M : public X, public Y
{
    void fx1() { cout << "M::fx1()" << endl; }
    void fy1() { cout << "M::fy1()" << endl; }
};

int main()
{
    X x;
    cout << "X:" << endl;
    cout << "sizeof(X) = " << sizeof(X) << endl;
    cout << "vptr address: " << (&x) << endl;
    cout << "x.a address: " << &x.a << endl;
    cout << "x.b address: " << &x.b << endl;

    Y y;
    cout << "Y:" << endl;
    cout << "sizeof(Y) = " << sizeof(Y) << endl;
    cout << "vptr address: " << (&y) << endl;

    M m;
    cout << "M:" << endl;
    cout << "sizeof(M) = " << sizeof(M) << endl;
    cout << "vptr address: " << (&m) << endl;
    cout << "m.a address: " << &m.a << endl;
    cout << "m.b address: " << &m.b << endl;

    using f = void (*)();
    f funx = reinterpret_cast<f>(*(int*)(&x));
    f x1 = reinterpret_cast<f>(((int*)funx)[0]);
    f x2 = reinterpret_cast<f>(((int*)funx)[1]);
    x1();
    x2();

    f funy = reinterpret_cast<f>(*(int*)(&y));
    f y1 = reinterpret_cast<f>(((int*)funy)[0]);
    f y2 = reinterpret_cast<f>(((int*)funy)[1]);
    y1();
    y2();

    f funmx = reinterpret_cast<f>(*(int*)(&m));
    f mx1 = reinterpret_cast<f>(((int*)funmx)[0]);
    f mx2 = reinterpret_cast<f>(((int*)funmx)[1]);
    mx1();
    mx2();

    f funmy = reinterpret_cast<f>(((int*)(&m))[3]);
    f my1 = reinterpret_cast<f>(((int*)funmy)[0]);
    f my2 = reinterpret_cast<f>(((int*)funmy)[1]);
    my1();
    my2();

    return 0;
}

其中,M没有覆盖X中的fx2(),因此M中虚函数fx2()的地址与X中虚函数fx2()的地址相同,都指向X中的虚函数fx2();M覆盖了X中的fx1(),因此M中虚函数fx1()的地址与X中虚函数fx1()的地址不相同,分别指向X和M中的虚函数。M和Y的关系与之类似。

运行时的内存结果如下:
在这里插入图片描述
程序运行结果如下:
在这里插入图片描述
x、y、m的内存布局如下:
在这里插入图片描述

1.4、虚继承

1.4.1、单一虚继承

#include <iostream>
using namespace std;

class X
{
public:
    int a = 0;
    int b = 1;
    virtual void fx1() { cout << "X::fx1()" << endl; }
};

class Y :virtual public X
{
public:
    virtual void fy1() { cout << "Y::fy1()" << endl; }
};

class Z :virtual public X
{
public:
    virtual void fz1() { cout << "Z::fz1()" << endl; }
    void fx1() { cout << "Z::fx1()" << endl; }
};

int main()
{
    X x;
    cout << "X:" << endl;
    cout << "sizeof(X) = " << sizeof(X) << endl;
    cout << "vptr address: " << (&x) << endl;
    cout << "x.a address: " << &x.a << endl;
    cout << "x.b address: " << &x.b << endl;

    Y y;
    cout << "Y:" << endl;
    cout << "sizeof(Y) = " << sizeof(Y) << endl;
    cout << "vptr address: " << (&y) << endl;
    cout << "y.a address: " << &y.a << endl;
    cout << "y.b address: " << &y.b << endl;

    Z z;
    cout << "Z:" << endl;
    cout << "sizeof(Z) = " << sizeof(Z) << endl;
    cout << "vptr address: " << (&z) << endl;
    cout << "z.a address: " << &z.a << endl;
    cout << "z.b address: " << &z.b << endl;

    using f = void (*)();
    f funx = reinterpret_cast<f>(*(int*)(&x));
    f x1 = reinterpret_cast<f>(((int*)funx)[0]);
    x1();

    f funy = reinterpret_cast<f>(*(int*)(&y));
    f y1 = reinterpret_cast<f>(((int*)funy)[0]);
    y1();

    f funyx = reinterpret_cast<f>(*((int*)(&y) + 2));
    f yx1 = reinterpret_cast<f>(((int*)funyx)[0]);
    yx1();

    f funz = reinterpret_cast<f>(*(int*)(&z));
    f z1 = reinterpret_cast<f>(((int*)funz)[0]);
    z1();

    f funzx = reinterpret_cast<f>(*((int*)(&z) + 2));
    f zx1 = reinterpret_cast<f>(((int*)funzx)[0]);
    zx1();

    return 0;
}

其中,Y通过虚继承的方式继承于X,在Y的对象中,首先存放的是Y的虚函数地址,接下来存放的是虚基类表指针,然后是Y的数据成员,最后是X的子对象。在虚基类表中存放的是偏移值,第一个是虚基类表指针距离子对象Y的偏移,第二个是距离虚基类子对象X的偏移。在Y中没有覆盖X的虚函数,因此Y中虚函数fx1()的地址与X中虚函数fx1()的地址相同,都指向X中的虚函数fx1();Z覆盖了X中的fx1(),因此Z中虚函数fx1()的地址与X中虚函数fx1()的地址不相同,分别指向Z和X中的虚函数fx1()。

运行时的内存结果如下:
在这里插入图片描述
程序运行结果如下:
在这里插入图片描述

x、y、z的内存布局如下:
在这里插入图片描述

在这里插入图片描述

1.4.2、多重虚继承

#include <iostream>
using namespace std;

class X
{
public:
    int a = 0;
    int b = 1;
    virtual void fx1() { cout << "X::fx1()" << endl; }
};

class Y :virtual public X
{
public:
    int c = 2;
    virtual void fy1() { cout << "Y::fy1()" << endl; }
};

class Z :virtual public X
{
public:
    virtual void fz1() { cout << "Z::fz1()" << endl; }
};

class M :public Y, public Z
{
public:
    int d = 3;
    virtual void fm1() { cout << "M::fm1()" << endl; }
    void fx1() { cout << "M::fx1()" << endl; }
};

int main()
{
    X x;
    cout << "X:" << endl;
    cout << "sizeof(X) = " << sizeof(X) << endl;
    cout << "vptr address: " << (&x) << endl;
    cout << "x.a address: " << &x.a << endl;
    cout << "x.b address: " << &x.b << endl;

    Y y;
    cout << "Y:" << endl;
    cout << "sizeof(Y) = " << sizeof(Y) << endl;
    cout << "vptr address: " << (&y) << endl;
    cout << "y.a address: " << &y.a << endl;
    cout << "y.b address: " << &y.b << endl;
    cout << "y.c address: " << &y.c << endl;

    Z z;
    cout << "Z:" << endl;
    cout << "sizeof(Z) = " << sizeof(Z) << endl;
    cout << "vptr address: " << (&z) << endl;
    cout << "z.a address: " << &z.a << endl;
    cout << "z.b address: " << &z.b << endl;

    M m;
    cout << "M:" << endl;
    cout << "sizeof(M) = " << sizeof(M) << endl;
    cout << "vptr address: " << (&m) << endl;
    cout << "m.a address: " << &m.a << endl;
    cout << "m.b address: " << &m.b << endl;
    cout << "m.c address: " << &m.c << endl;
    cout << "m.d address: " << &m.d << endl;

    using f = void (*)();
    f funx = reinterpret_cast<f>(*(int*)(&x));
    f x1 = reinterpret_cast<f>(((int*)funx)[0]);
    x1();

    f funy = reinterpret_cast<f>(*(int*)(&y));
    f y1 = reinterpret_cast<f>(((int*)funy)[0]);
    y1();

    f funyx = reinterpret_cast<f>(*((int*)(&y) + 3));
    f yx1 = reinterpret_cast<f>(((int*)funyx)[0]);
    yx1();

    f funz = reinterpret_cast<f>(*(int*)(&z));
    f z1 = reinterpret_cast<f>(((int*)funz)[0]);
    z1();

    f funzx = reinterpret_cast<f>(*((int*)(&z) + 2));
    f zx1 = reinterpret_cast<f>(((int*)funzx)[0]);
    zx1();

    f funm = reinterpret_cast<f>(*(int*)(&m));
    f m1 = reinterpret_cast<f>(((int*)funm)[0]);
    m1();

    f funmy = reinterpret_cast<f>(*((int*)(&m)));
    f my1 = reinterpret_cast<f>(((int*)funmy)[0]);
    my1();

    f funmz = reinterpret_cast<f>(*((int*)(&m) + 3));
    f mz1 = reinterpret_cast<f>(((int*)funmz)[0]);
    mz1();

    f funmx = reinterpret_cast<f>(*((int*)(&m) + 6));
    f mx1 = reinterpret_cast<f>(((int*)funmx)[0]);
    mx1();

    return 0;
}

在M的对象中,首先存放的是Y的子对象,需要注意的是:M中的虚函数地址存放在Y的子对象的虚函数表中,接下来是Z的子对象,然后是M的数据成员,最后是X的子对象。

运行时的内存结果如下:
在这里插入图片描述

程序运行结果如下:
在这里插入图片描述

x、y、z、m的内存布局如下:
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值