前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++虚函数表

c++虚函数表

作者头像
changan
发布2020-12-23 11:43:39
6580
发布2020-12-23 11:43:39
举报
文章被收录于专栏:巡天遥看一千河

概述

首先,相较于C语言,C++语言并没有额外增加内存消耗(确切说,在没有虚函数情况下)。 对于一个C++类对象,每个对象有独立的数据成员(非static),但是内存中成员函数只有一份,该类的所有对象共享成员函数。

编译器在编译阶段,进行函数的重构,即将成员函数进行非成员化。通过将this指针作为函数的第一个参数,通过this指针即可以找到对象的数据成员

使用GDB调试 C++ 虚函数

代码语言:javascript
复制
class Base
{
public:
        int a;
        int b;
        virtual void function(){}
        virtual void function001(){}

        Base(){}
        void NotVirtFunc(){}
};

class Derive : public Base
{
public:
    Derive(){}
    int c;
    virtual void function(){}
    virtual void function006(){}
};

class Test
{
    public:
    int vv;
    virtual void bar(){}
    virtual void foo(){}

    Test(){}
};

class Derive2 : public Derive, public Test
{
public:
    Derive2(){}
    int d2;
    virtual void function(){}
    virtual void function006(){}
    virtual void bar(){}
};

int main()
{
    Base b;                         // 没有继承
    b.function();

    Derive d;                       // 继承
    d.function();

    Derive2* d2 = new Derive2();    //多继承
    d2->function();
    delete d2;
    return 0;
}
代码语言:javascript
复制
(gdb) p b
$1 = {_vptr.Base = 0x400a90 <vtable for Base+16>, a = 0, b = 0}
(gdb) info vtbl b
vtable for 'Base' @ 0x400a90 (subobject @ 0x7fffffffe2e0):
[0]: 0x40081e <Base::function()>
[1]: 0x400828 <Base::function001()>
image
image
代码语言:javascript
复制
(gdb) p d
$2 = {<Base> = {_vptr.Base = 0x400a50 <vtable for Derive+16>, a = 0, b = 0}, c = 1}
(gdb) info vtbl d
vtable for 'Derive' @ 0x400a50 (subobject @ 0x7fffffffe2c0):
[0]: 0x40086e <Derive::function()>
[1]: 0x400828 <Base::function001()>
[2]: 0x400878 <Derive::function006()>
image
image
代码语言:javascript
复制
(gdb) p *d2        
$5 = {<Derive> = {<Base> = {_vptr.Base = 0x4009d0 <vtable for Derive2+16>, a = 0, b = 0}, c = 0}, 
        <Test> = {_vptr.Test = 0x400a00 <vtable for Derive2+64>, vv = 0}, d2 = 0}
(gdb) info vtbl d2
vtable for 'Derive2' @ 0x4009d0 (subobject @ 0x603010):
[0]: 0x4008ee <Derive2::function()>
[1]: 0x400828 <Base::function001()>
[2]: 0x4008f8 <Derive2::function006()>
[3]: 0x400902 <Derive2::bar()>

vtable for 'Test' @ 0x400a00 (subobject @ 0x603028):
[0]: 0x40090c <non-virtual thunk to Derive2::bar()>
[1]: 0x40088c <Test::foo()>
image
image
构造函数与虚函数表

虚函数表创建时机是在编译期间。 编译期间编译器就为每个类确定好了对应的虚函数表里的内容。 所以在程序运行时,编译器会把虚函数表的首地址赋值给虚函数表指针,所以,这个虚函数表指针就有值了。

image
image

ref

TODO

菱形继承于虚继承这里没写,使用gdb也可以很快找到,编译器的规则而已,同理,后面这两种知道规则就可以了,在语言的框架下理解就可以了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 使用GDB调试 C++ 虚函数
    • 构造函数与虚函数表
    • ref
    • TODO
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档