gpt4 book ai didi

c++ - 为什么编译器会向 lib 添加内联类方法?

转载 作者:行者123 更新时间:2023-11-30 03:20:38 25 4
gpt4 key购买 nike

考虑一个属于链接到动态库 (foo.dll) 的项目的类,同时也在侧面生成 foo.lib:

class IMP_EXP_DIRECTIVE_MACRO Foo
{
void bar()
{
// do something
}
};

然后还有一个项目bar(生成静态库bar.lib)包含了这个类。该项目未与 foo 链接。

最后有一个应用程序项目(生成 .exe),它与 foo.lib 和 bar.lib 都链接。当它发生时,链接器会发出 LNK2005 错误提示,即 Foo::bar 已在 foo.lib(这很好)和 bar.lib 中定义,这是意外且奇怪的。

根据 https://learn.microsoft.com/en-us/cpp/build/reference/symbols?view=vs-2017 使用 dumpbin.exe/SYMBOLS 处理 bar.lib 时输出显示 Foo::bar 确实在 foo.lib (!) 中定义。这很奇怪,因为根据这个辉煌 https://stackoverflow.com/a/4955288答案是,在类的主体中声明和定义的任何成员函数都是隐式内联的,因此不会导致 ODR 问题。

最后,最有趣的部分。将 Foo::bar 定义移动到 .cpp 文件并在类主体中仅保留方法声明时,问题就消失了。

为什么会这样?知道做错了什么吗?我想我已经阅读了整个互联网上关于这个主题的内容并尝试了所有各种 VS 配置开关,但只有将定义移动到 .cpp 才有帮助。原则上我最终可以做到,但这似乎不是解决问题的合适方法。

环境是:Visual Studio 10。

编辑:
IMP_EXP_DIRECTIVE_MACRO 设置为:
“__declspec(dllexport)”,构建 foo.dll 时
"", 构建栏时

编辑 2:
问题也消失了,在编译 bar.lib 时添加了一个预处理器标志,导致使用 class __declspec(dllimport) Foo 而不是 class Foo
这是正确的方法吗?

最佳答案

该函数可内联

但是如果你取它的地址&Foo::bar,编译器仍然需要一个真实的地址。这实际上意味着指向的地址必须有非内联代码。结果是编译器必须在每个翻译单元中放置一个拷贝,链接器将选择其中一个 - 每个链接器输出一个。但是 Foo.lib 的链接器无法预测 Bar.lib 中也会有一个拷贝,反之亦然。

关于c++ - 为什么编译器会向 lib 添加内联类方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52737676/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com