考虑一个属于链接到动态库 (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://docs.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 时
“”,在构建 bar 时
编辑 2:
问题也消失了,当在编译 bar.lib 时添加了一个预处理器标志,导致class __declspec(dllimport) Foo
使用而不是class Foo
.
这是正确的方法吗?