我有以下代码(涉及多个文件)...
//--- SomeInterface.h
struct SomeInterface
{
virtual void foo() = 0;
virtual ~SomeInterface(){}
};
//--- SomeInterfaceUser.h
#include <memory> //shared_ptr
class SomeInterface;
//NOTE: struct SomeInterface... causes linker error to go away...
class SomeInterfaceUser
{
public:
explicit SomeInterfaceUser(std::shared_ptr<SomeInterface> s);
};
//SomeInterfaceUser.cpp
#include "SomeInterfaceUser.h"
#include "SomeInterface.h"
SomeInterfaceUser::SomeInterfaceUser(std::shared_ptr<SomeInterface> s)
{
}
//SomerInterfaceUserInstantiator.cpp
#include "SomeInterfaceUser.h"
#include "SomeInterfaceImpl.h"
struct SomeInterfaceImpl : SomeInterface
{
virtual void foo(){}
};
void test()
{
SomeInterfaceUser x{std::make_shared<SomeInterfaceImpl>()};
}
Run Code Online (Sandbox Code Playgroud)
使用Visual C ++编译器,我得到一个链接器错误(LNK2019)。使用GCC 4.8.4并非如此。将前向声明类SomeInterface更改为struct SomeInterface可使链接器错误消失。我一直以为应该可以互换使用类/结构?SomeInterfaceUser的接口不应取决于SomeInterface是定义为类还是struct,不是吗?
这是Visual C ++错误吗?我找不到任何与此有关的东西。我怀疑将struct用作模板参数这一事实与它有关。
感谢您的帮助。
我刚刚在 VC++ 2010 和 VC++ 2017 中都遇到了同样的问题,经过一些测试,我发现问题在于编译器在内部为结构和类提供的符号名称。
这是一个包含三个文件的最小示例:
主程序
#include "bar.h"
struct Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
酒吧.h
class Foo;
void bar(Foo* f);
Run Code Online (Sandbox Code Playgroud)
bar.cpp
#include "bar.h"
void bar(Foo* foo) {}
Run Code Online (Sandbox Code Playgroud)
编译项目时出现以下错误和警告:
警告 C4099:“Foo”:首先使用“class”看到的类型名称现在使用“struct”看到
见'Foo'的声明
错误 LNK2019:未解析的外部符号“void __cdecl bar(struct Foo *)”(?bar@@YAXPAUFoo@@@Z) 在函数 _main 中引用
致命错误 LNK1120:1 个未解析的外部
现在,我换了struct
,并class
声明,所以main.cpp
和bar.h
现在:
主程序
#include "bar.h"
class Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
酒吧.h
struct Foo;
void bar(Foo* f);
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,错误仍然弹出:
错误 LNK2019:函数 _main 中引用了未解析的外部符号“void __cdecl bar(class Foo *)”(?bar@@YAXPAVFoo@@@Z)
但是,这是有趣的部分,请参阅main()
每种情况下预期函数的符号(在 中使用的符号)不同:
?bar@@YAXPAUFoo@@@Z(当参数为 a 时struct
)
?bar@@YAXPAVFoo@@@Z(当参数为 a 时class
)
结论
如果类型是结构体或类,编译器给出的名称略有不同。
然后链接器找不到正确的定义,因为它正在寻找不同的bar.cpp
定义:使用前向声明定义一个,但目前它在main.cpp
实际声明中被调用,因此符号表中给出了不同的函数名称.
归档时间: |
|
查看次数: |
731 次 |
最近记录: |