向前将结构声明为类时出现Visual C ++ 2015链接器错误 [英] Visual C++ 2015 linker error when forward declaring a struct as class
问题描述
我有以下代码(涉及多个文件)...
//-SomeInterface.h结构SomeInterface{虚拟void foo()= 0;虚拟〜SomeInterface(){}};//-SomeInterfaceUser.h#include< memory>//shared_ptr类SomeInterface;//注意:struct SomeInterface ...导致链接器错误消失...类SomeInterfaceUser{上市:明确的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{虚拟虚空foo(){}};无效测试(){SomeInterfaceUser x {std :: make_shared< SomeInterfaceImpl>()};}
使用Visual C ++编译器,出现链接器错误(LNK2019).使用GCC 4.8.4并非如此.将前向声明类SomeInterface 更改为 struct SomeInterface 可以使链接程序错误消失.我一直以为应该可以互换使用类/结构?SomeInterfaceUser的接口不应取决于SomeInterface是定义为类还是结构,不是吗?
这是Visual C ++错误.我找不到任何与此有关的东西.我怀疑将struct用作模板参数这一事实与之有关.
感谢您的帮助.
我刚刚在VC ++ 2010和VC ++ 2017中都遇到了同样的问题,经过一些测试,我发现问题出在符号名称上编译器在内部提供结构和类.
这是一个由三个文件组成的最小示例:
main.cpp
#include"bar.h"struct Foo {};int main(){Foo foo;bar(& foo);返回0;}
bar.h
Foo类;空条(Foo * f);
bar.cpp
#include"bar.h"void bar(Foo * foo){}
编译项目时,出现以下错误和警告:
警告C4099:"Foo":键入最初使用类"看到的名称,现在使用结构"看到
请参阅"Foo"的声明
错误LNK2019:未解析的外部符号"void __cdecl bar(struct Foo *)"_main函数中引用的(?bar @@ YAXPAUFoo @@@@ Z)
致命错误LNK1120:1个未解决的外部因素
现在,我交换了 struct
和 class
声明,所以 main.cpp
和 bar.h
是现在:
main.cpp
#include"bar.h"Foo类{};int main(){Foo foo;bar(& foo);返回0;}
bar.h
struct Foo;空条(Foo * f);
按预期,该错误仍然会弹出:
错误LNK2019:未解析的外部符号"void __cdecl bar(Foo *类)"_main函数中引用的(?bar @@ YAXPAVFoo @@@@ Z)
BUT ,这是有趣的部分,请参见每种情况下预期功能的符号(在 main()
中使用的符号)不同:>
-
?bar @@ YAXPAUFoo @@@ Z (当参数为
struct
时) -
?bar @@ YAXPAVFoo @@@ Z (当参数是
class
时)
结论
如果类型是结构或类,则编译器提供的名称稍有不同.
然后,链接器找不到正确的定义,因为它正在寻找不同的定义: bar.cpp
使用正向声明定义了一个,但是暂时在 main中调用了它.cpp
放置了实际的声明,因此在符号表中指定了不同的函数名称.
I have the following code (more than one file involved)...
//--- 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>()};
}
Using the Visual C++ compiler, I get a linker error (LNK2019). Using GCC 4.8.4 this is not the case. Changing the forward declaration class SomeInterface to struct SomeInterface makes the linker error go away. I always thought that one should be able to use class/struct interchangeably? The interface of SomeInterfaceUser should not depend on whether SomeInterface is defined as class or struct, not so?
Is this a Visual C++ bug. I cannot find anything relating to it. I suspect the fact that the struct is used as template parameter has something to do with it.
Your help appreciated.
I've just been facing the same problem with both VC++ 2010 and VC++ 2017, and after some tests I've found that the problem resides in the symbol name the compiler gives to structs and classes internally.
Here a minimum example consisting in three files:
main.cpp
#include "bar.h"
struct Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
bar.h
class Foo;
void bar(Foo* f);
bar.cpp
#include "bar.h"
void bar(Foo* foo) {}
When the project is compiled the following errors and warnings appear:
warning C4099: 'Foo': type name first seen using 'class' now seen using 'struct'
see declaration of 'Foo'
error LNK2019: unresolved external symbol "void __cdecl bar(struct Foo *)" (?bar@@YAXPAUFoo@@@Z) referenced in function _main
fatal error LNK1120: 1 unresolved externals
Now, I swapped the struct
and class
declarations, so main.cpp
and bar.h
are now:
main.cpp
#include "bar.h"
class Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
bar.h
struct Foo;
void bar(Foo* f);
As expected, the error still pops up:
error LNK2019: unresolved external symbol "void __cdecl bar(class Foo *)" (?bar@@YAXPAVFoo@@@Z) referenced in function _main
BUT, and this is the interesting part, see that the symbols for the expected function (the one used in main()
) in each case differ:
?bar@@YAXPAUFoo@@@Z (when the parameter is a
struct
)?bar@@YAXPAVFoo@@@Z (when the parameter is a
class
)
Conclusion
The compiler gives slightly different names if the type is a struct or a class.
The linker then cannot find the proper definition because it is looking for a different one: bar.cpp
defines one with the forward declaration, but for the moment it is called in main.cpp
the actual declaration has taken placed, so a different function name is given in the symbols table.
这篇关于向前将结构声明为类时出现Visual C ++ 2015链接器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!