c++ - 虚函数在哪里使用 vpointers to vtables 来解析方法调用,非虚方法存储在哪里以及它们是如何解析的?

标签 c++ methods vtable

具有定义的类

class A
{
    void AFunc1(){}
    void AFunc2(){}
    void AFunc3(){}
    virtual void AVirtualFunc1(){}
};

由于隐藏的 vpointer 成员指向具有指针的共享 vtable,因此 sizeof() 的值为 4 个字节方法。

但是,类的一个实例

class B
{
    void BFunc1(){}
    void BFunc2(){}
    void BFunc3(){}
};

将只有 1 个字节的 sizeof() 值,因为不需要 vpointer 并且也不存在 vtable .如果是这样,函数 BFunc1()BFunc2()BFunc3() 存储在哪里以及它们如何被引用对象实例?

最佳答案

对于每个真正在某处使用的非虚函数,该函数的代码被发送到目标文件,如果代码来自包含的头文件并在多个翻译单元中使用,则可能在多个文件中。此外,符号也被插入到目标文件中。如果您是这样的 Linux 用户,您可以使用 nm 查看已定义方法/功能/...的表格:

nm main.o |c++filt

                    U __cxa_atexit
                    U __dso_handle
0000000000000062 t _GLOBAL__sub_I_main
0000000000000000 T main
0000000000000024 t __static_initialization_and_destruction_0(int, int)
0000000000000000 W A::AVirtualFunc1()
0000000000000000 W A::AFunc1()
0000000000000000 r __gnu_cxx::__default_lock_policy
                    U std::ios_base::Init::Init()
                    U std::ios_base::Init::~Init()
0000000000000000 b std::__ioinit
0000000000000000 V typeinfo for A
0000000000000000 V typeinfo name for A
0000000000000000 V vtable for A
                    U vtable for __cxxabiv1::__class_type_info

如您所见,A::AFunc1() 被定义为一个符号。它被定义为弱,因为我们可以在不同的翻译单元中有多个实例,但我们知道,它们都是相同的。 (这就是我们在 C++ 中拥有“单一定义规则”的原因)。顺便说一句:如果您有多个使用相同标签的定义,则链接器也只放置一个并且也没有错误消息。您的程序的行为不是由链接顺序定义的。非常糟糕的事情!回到弱符号,如果我们多次将相同的方法存储在目标文件中,链接器不应发出错误。链接器现在可以简单地选择其中之一而不会出现任何错误消息。例如,main 函数在表中标记为“T”。如果您多次使用 T 标记相同的符号,链接器将为多个定义的函数发出错误消息。

你看,符号在目标文件中的地址是0000000,也就是说,它目前没有地址。该地址将在静态可执行文件的链接时或程序启动时的动态链接时重新定位。

如您所见,虚函数也以相同的方式存储,并且没有任何区别。也可以使用 A::AVirtualFunc 调用方法本身,而无需跳过 vtable。

您还可以看到,vtable 本身是目标文件的一部分并标记为 V。您还可以在多个目标文件中拥有相同的 vtable。链接器在最终链接中也只采用其中一个。

关于c++ - 虚函数在哪里使用 vpointers to vtables 来解析方法调用,非虚方法存储在哪里以及它们是如何解析的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57121836/

相关文章:

c++ - 列表迭代器错误 : "no match for operator+" ,

c++ - 派生类是否可以有多个指向虚拟表的指针?

c++ - 两个 std::List 之间的距离

c++ - 在 C++ 中通过 UDP 套接字发送结构、 float 和整数

go - Go 如何将方法绑定(bind)到对象?

java - 我自己的数组列表

c++ - 下面的代码创建了多少个虚拟表?

c++ - 是否可以在vtable中更改任何func指针?

c++ - 带有 g++ 的不需要的警告消息

java - 最短字符串长度显示在主方法中,但放置在另一个方法中时不显示