向前将结构声明为类时出现Visual C ++ 2015链接器错误 [英] Visual C++ 2015 linker error when forward declaring a struct as class

查看:54
本文介绍了向前将结构声明为类时出现Visual C ++ 2015链接器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码(涉及多个文件)...

 //-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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆