ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

类的内存结构

2020-06-18 10:04:11  阅读:344  来源: 互联网

标签:虚表 函数 void virtual gdb int64 内存 结构


cpp 类的内存结构

说明:

  1. 虚表指针总是存在在类的头部,并按类的继承顺序排放。一个子类可以有多个虚表指针。

  2. 虚成员函数总是按照声明顺序存在于虚表中。

  3. 如果存在同名函数,子类虚函数会覆盖每一个父类的每一个同名虚函数。

  4. 子类独有的虚函数填入第一个虚函数表中,且用父类指针是不能调用。

  5. 父类独有的虚函数不会被覆盖覆盖。仅子类和该父类指针能调用。

如下图类的内存结构图

图中代码参考链接

无继承

代码:

class Drive
{
public:
    virtual void vf() {}
    void f() {}
};

int main()
{
    Drive d;

    return 0;
}

如下,子类经过强制类型转换,得到虚表指针,并提取虚表指针的内容,经过转换可以得到第一个虚函数。虚表中只有一个虚函数。

(gdb) b 69
Breakpoint 1 at 0x13c1: file xx.cpp, line 69.
(gdb) r
Starting program: /home/lester/tools/xxx/a.out 

Breakpoint 1, main () at xx.cpp:69
69	    return 0;
(gdb) p d
$1 = {_vptr.Drive = 0x555555557da0 <vtable for Drive+16>}
(gdb) p (int64_t*)*(int64_t*)d
$2 = (int64_t *) 0x55555555543a <Drive::vf()>
(gdb) 

单继承

class Base1
{
public:
    virtual void vb1f() {}
    virtual void vf() {}
};

class Drive : public Base1
{
public:
    virtual void vdf() {}
    virtual void vf() {}
    void f() {}
};

int main()
{
    Drive d;

    return 0;
}

虚表中只有多个虚函数。顺序是父类,子类的顺序。其中注意到双方共有的虚函数 “vf”, 在虚表中子类的虚函数覆盖了父类的需函数。

(gdb) b 70
Breakpoint 1 at 0x13c1: file xx.cpp, line 70.
(gdb) r
Starting program: /home/lester/tools/xxx/a.out 

Breakpoint 1, main () at xx.cpp:70
70	    return 0;
(gdb) p (int64_t*)*((int64_t*)d+0)
$1 = (int64_t *) 0x55555555543a <Base1::vb1f()>
(gdb) p (int64_t*)*((int64_t*)d+1)
$2 = (int64_t *) 0x555555555452 <Drive::vf()>
(gdb) p (int64_t*)*((int64_t*)d+2)
$3 = (int64_t *) 0x555555555446 <Drive::vdf()>
(gdb) 

多继承

class Base1
{
public:
    virtual void vb1f() {}
    virtual void vf() {}
};

class Base2
{
public:
    virtual void vb2f() {}
    virtual void vf() {}
};

class Drive : public Base1, Base2
{
public:
    virtual void vdf() {}
    virtual void vf() {}
    void f() {}
};

int main()
{
    Drive d;

    return 0;
}

虚表中只有多个虚函数。顺序是父类Base1, 父类Base2,子类。

查看第一个虚表:其中注意到双方共有的虚函数 “vf”, 在虚表中子类的虚函数覆盖了父类的需函数。另外子类的虚函数 ”vdf“ 被放在了第一个虚表的后面。

查看第二个虚表:第二个虚表指针在地一个虚表指针后面。同样方式可以看到第二个虚表只有父类 Base2 的虚成员函数,而且共有的虚函数被子类的虚函数 vf 覆盖。

(gdb) b 71
Breakpoint 1 at 0x13cc: file xx.cpp, line 71.
(gdb) r
Starting program: /home/lester/tools/xxx/a.out 

Breakpoint 1, main () at xx.cpp:71
71	    return 0;
(gdb) 
(gdb) p d
$10 = {<Base1> = {_vptr.Base1 = 0x555555557d28 <vtable for Drive+16>}, <Base2> = {_vptr.Base2 = 0x555555557d50 <vtable for Drive+56>}, <No data fields>}
(gdb) p (int64_t*)*((int64_t*)d+0)
$1 = (int64_t *) 0x555555555446 <Base1::vb1f()>
(gdb) p (int64_t*)*((int64_t*)d+1)
$2 = (int64_t *) 0x55555555546a <Drive::vf()>
(gdb) p (int64_t*)*((int64_t*)d+2)
$3 = (int64_t *) 0x55555555545e <Drive::vdf()>


(gdb) p d
$10 = {<Base1> = {_vptr.Base1 = 0x555555557d28 <vtable for Drive+16>}, <Base2> = {_vptr.Base2 = 0x555555557d50 <vtable for Drive+56>}, <No data fields>}
(gdb) p (int64_t*)*((int64_t*)*(int64_t*)((int64_t*)&d+1)+0)
$12 = (int64_t *) 0x555555555452 <Base2::vb2f()>
(gdb) p (int64_t*)*((int64_t*)*(int64_t*)((int64_t*)&d+1)+1)
$13 = (int64_t *) 0x555555555475 <non-virtual thunk to Drive::vf()>
(gdb) 

标签:虚表,函数,void,virtual,gdb,int64,内存,结构
来源: https://www.cnblogs.com/sinpo828/p/13156042.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有