链接器如何处理在多个标头中定义的虚拟函数

How does linker deal with virtual functions defined in multiple headers?

本文关键字:定义 函数 虚拟 何处理 处理 链接      更新时间:2023-10-16

假设我有

Base.h
class Base
{
    virtual void foo() {...}
};

Derived1.h
class Derived1 : public Base
{
    virtual void foo() {...}
};

Derived2.h
class Derived2 : public Base
{
    virtual void foo() {...}
};

Derived1.h包含在多个源文件中,Derived1类也通过Base接口使用。由于foovirtual并且是使用polymorphic的,所以它不能内联。因此,它将被编译在多个obj文件中。链接器如何解决这种情况?

类定义中定义的成员函数是隐式inlineC++03 7.1.2.3)。
函数体是否真的在调用时内联是无关紧要的。但是inline允许您拥有一个函数的多个定义,只要所有定义都相同(这是一个定义规则不允许的)(C++03 7.1.2.2)。标准要求链接器应该能够链接到这些定义中的(一个或多个)。(C++03 7.1.2.4)。

链接器是如何做到这一点的

对此的标准规定如下:

  • 它要求每个翻译单位都有职能定义。链接器所要做的就是链接到该翻译单元中的定义
  • 它规定,该职能的所有定义都应完全相同,这消除了在存在不同定义的情况下链接到特定定义的任何歧义

C++03 7.1.2函数说明符:
第2段:

带有内联说明符的函数声明(8.3.5、9.3、11.4)声明了一个内联函数。内联说明符向实现指示,与通常的函数调用机制相比,在调用点对函数体的内联替换更可取。在调用点执行此内联替换不需要实现;然而,即使省略了这种内联替换,仍应遵守7.1.2中定义的内联函数的其他规则。

第3段:

类定义中定义的函数是内联函数。内联说明符不应出现在块作用域函数声明上

第4段:

内联函数应在使用它的每个翻译单元中定义,并且在任何情况下都应具有完全相同的定义(3.2)