为啥一个成员函数只存在一次,甚至在一个包含多个的 .h 文件中定义? [复制]

Posted

技术标签:

【中文标题】为啥一个成员函数只存在一次,甚至在一个包含多个的 .h 文件中定义? [复制]【英文标题】:Why does a member function exist only once even defined in one multiple included .h file? [duplicate]为什么一个成员函数只存在一次,甚至在一个包含多个的 .h 文件中定义? [复制] 【发布时间】:2016-06-29 00:41:58 【问题描述】:

我只是想知道编译器如何处理仅在包含文件中声明和定义成员函数但此 .h 文件多次包含在不同源代码中而不抱怨链接器关于 multiple definition of ... 的情况。

foo_1.h:

class foo

public:
    auto in_include() -> void  printf( "in in_include()\n" ); 
    foo();
;

foo_1.cpp:

#include <stdio.h>
#include "foo_1.h"

foo::foo()

        printf( "in foo()\n" );
        in_include();

最后是foo_main.cpp:

#include <stdio.h>
#include "foo_1.h"

int main()

        foo fooObject;

这些 MCVE 可以很好地编译 链接并产生预期的输出:

in foo()
in in_include()

但是,当我添加foo_1.h 这一行int globar_var; 然后链接器抱怨[如我所料]:

/tmp/ccfjJJAT.o:(.bss+0x0): multiple definition of `globar_var'
/tmp/cciob9sM.o:(.bss+0x0): first defined here

我确实将其视为重复,因为我问为什么链接器不抱怨。另一个问题或多或少地问为什么可以在头文件中定义函数。

【问题讨论】:

auto foo() -&gt; void 是一种非常复杂的表达方式void foo() 在类中完整定义的函数隐含为inline,因此它们避开了通常的 ODR 规则。在类之外定义该函数,但仍在标题和观察中。 @AlBundy 这是一个不同的措辞,但最后你们都想知道内联成员函数定义是如何工作的,那里的答案解释了这一点。 “另一个问题或多或少地问为什么可以在头文件中定义函数。”你的也是。 @AlBundy:我同意 BaummitAugen,因为其他主题中的答案只是告诉您成员函数的就地定义是隐式内联的,这就是 why 链接器的原因不抱怨。因为标准是这样说的。链接器不抱怨的原因与可以在头文件中定义函数的原因相同:如果(隐式)内联,它才有效。 您为什么不同意建议的副本?它对我来说看起来很准确。它询问在类定义中内联定义的函数以及为什么它不会造成麻烦——这也是你要问的。 【参考方案1】:

在类声明中使用主体定义的类成员函数会自动成为内联函数,因此即使定义被多次编译也可以。您可以使用 inline 关键字获得相同的非类函数。

这在实践中如何实现取决于编译器 - 它实际上可以在每次调用代码时内联代码(想想复制和粘贴),或者它可以安排一些我不完全理解的链接器魔术来防止发生碰撞。

【讨论】:

以上是关于为啥一个成员函数只存在一次,甚至在一个包含多个的 .h 文件中定义? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

静态构造函数, 静态成员初始化/调用顺序

总结一些笔记上的C和C++知识点

为啥我的函数在每次页面加载时只运行一次?

为啥 NSTimer 在 swift 中只工作一次

为啥 gprof 告诉我一个只从 main() 调用一次的函数被调用了 102 次?

为啥 C++17 中的全局内联变量和静态内联成员需要守卫?