Main.obj 中已定义错误 LINK2005
Error LINK2005 already defined in Main.obj
我有这个问题,如果我包含某个 header,我将无法编译。
header的代码:
//#include "tinyxml2.h"
#pragma once
#include "Camera.h"
#include "Controller.h"
#include "Lights.h"
#include "Mesh.h"
namespace ActorFactory {
//using namespace tinyxml2;
template<class T>
Actor* createInstance() {
return new T;
}
typedef std::map<std::string, Actor*(*)()> class_map;
class_map test = {
{ "Camera", &createInstance<Camera> }
//{ "Mesh", &createInstance<Mesh> }
};
}
来自 visual studio 的完整错误消息:
1>------ Build started: Project: ogl_inf251_ca2, Configuration: Debug Win32 ------
1> Main.cpp
1>d:\development\inf251\ogl_inf251_ca2\model_obj.h(26): warning C4005: '_CRT_SECURE_NO_WARNINGS' : macro redefinition
1> command-line arguments : see previous definition of '_CRT_SECURE_NO_WARNINGS'
1> Generating Code...
1> Compiling...
1> Scene.cpp
1>d:\development\inf251\ogl_inf251_ca2\model_obj.h(26): warning C4005: '_CRT_SECURE_NO_WARNINGS' : macro redefinition
1> command-line arguments : see previous definition of '_CRT_SECURE_NO_WARNINGS'
1> Generating Code...
1>Scene.obj : error LNK2005: "class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class Actor * (__cdecl*)(void),struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class Actor * (__cdecl*)(void)> > > ActorFactory::test" (?test@ActorFactory@@3V?$map@V? $basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@P6APAVActor@@XZU? $less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V? $allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V? $allocator@D@2@@std@@P6APAVActor@@XZ@std@@@2@@std@@A) already defined in Main.obj
1>D:\development\inf251\Debug\ogl_inf251_ca2.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
不幸的是,错误消息真的很长。我不知道如何解决这个问题,甚至不知道出了什么问题。还有更好的方法来实例化 类 的名字吗?
提前感谢您的帮助:)
它似乎在抱怨 test
的重新定义。试试重命名?
问题是你声明的方式test
。
您可以将其声明为 static
或 const
(在本例中表示 static
)。但是,对于包含此 header 的每个源文件,您将拥有 单独的 副本 test
,浪费内存并可能导致其他问题。
因此你应该在 header extern class_map test;
中声明你的测试,并且只在一个源文件中,把 ActorFactory::class_map ActorFactory::test = {...};
(如果你把它设为常量,把 extern 放在源文件位也是)。
我觉得你在 header 中实例化了 'test' 变量,它包含在 Main.Cpp 和 Scene.Cpp 中。没有?
如果您的 header 包含在两个 .cpp 文件中,则会导致符号重复。 #pragma once 仅防止在编译同一个源文件时多次包含 header,但在编译另一个源代码时仍然可以包含第二次。
您的 test
对象违反了单一定义规则。
#pragma once
使定义不会在相同的 编译单元中多次出现(阅读:相同的*. cpp 文件),但不会出现在 不同的 编译单元中(读取:不同的 *.cpp 文件)。
解决此问题的一种方法是将对象转换为函数内的静态本地对象,并使其可通过引用访问:
header.h:
// ...
namespace ActorFactory {
// ...
typedef std::map<std::string, Actor*(*)()> class_map;
class_map& test();
}
test.cpp:
#include "header.h"
namespace ActorFactory {
// ...
class_map& test() {
static class_map test = {
{ "Camera", &createInstance<Camera> }
{ "Mesh", &createInstance<Mesh> };
return test;
}
}
这也是针对所谓的 static initialization order fiasco 的故障安全保证,并为您提供惰性初始化(与这个小对象无关紧要)。
您可以通过使用 new
分配对象并且从不删除它来使整个事情更加安全(面对销毁顺序问题),但函数应该仍然 return 参考文献:
namespace ActorFactory {
// ...
class_map& test() {
static class_map* test = new class_map {
{ "Camera", &createInstance<Camera> }
{ "Mesh", &createInstance<Mesh> };
return *test;
}
}
阅读上面链接的常见问题解答以获取所有详细信息。
在任何情况下,客户端代码都可以通过 test()
而不是 test
访问对象。
我有这个问题,如果我包含某个 header,我将无法编译。
header的代码:
//#include "tinyxml2.h"
#pragma once
#include "Camera.h"
#include "Controller.h"
#include "Lights.h"
#include "Mesh.h"
namespace ActorFactory {
//using namespace tinyxml2;
template<class T>
Actor* createInstance() {
return new T;
}
typedef std::map<std::string, Actor*(*)()> class_map;
class_map test = {
{ "Camera", &createInstance<Camera> }
//{ "Mesh", &createInstance<Mesh> }
};
}
来自 visual studio 的完整错误消息:
1>------ Build started: Project: ogl_inf251_ca2, Configuration: Debug Win32 ------
1> Main.cpp
1>d:\development\inf251\ogl_inf251_ca2\model_obj.h(26): warning C4005: '_CRT_SECURE_NO_WARNINGS' : macro redefinition
1> command-line arguments : see previous definition of '_CRT_SECURE_NO_WARNINGS'
1> Generating Code...
1> Compiling...
1> Scene.cpp
1>d:\development\inf251\ogl_inf251_ca2\model_obj.h(26): warning C4005: '_CRT_SECURE_NO_WARNINGS' : macro redefinition
1> command-line arguments : see previous definition of '_CRT_SECURE_NO_WARNINGS'
1> Generating Code...
1>Scene.obj : error LNK2005: "class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class Actor * (__cdecl*)(void),struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class Actor * (__cdecl*)(void)> > > ActorFactory::test" (?test@ActorFactory@@3V?$map@V? $basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@P6APAVActor@@XZU? $less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V? $allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V? $allocator@D@2@@std@@P6APAVActor@@XZ@std@@@2@@std@@A) already defined in Main.obj
1>D:\development\inf251\Debug\ogl_inf251_ca2.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
不幸的是,错误消息真的很长。我不知道如何解决这个问题,甚至不知道出了什么问题。还有更好的方法来实例化 类 的名字吗?
提前感谢您的帮助:)
它似乎在抱怨 test
的重新定义。试试重命名?
问题是你声明的方式test
。
您可以将其声明为 static
或 const
(在本例中表示 static
)。但是,对于包含此 header 的每个源文件,您将拥有 单独的 副本 test
,浪费内存并可能导致其他问题。
因此你应该在 header extern class_map test;
中声明你的测试,并且只在一个源文件中,把 ActorFactory::class_map ActorFactory::test = {...};
(如果你把它设为常量,把 extern 放在源文件位也是)。
我觉得你在 header 中实例化了 'test' 变量,它包含在 Main.Cpp 和 Scene.Cpp 中。没有?
如果您的 header 包含在两个 .cpp 文件中,则会导致符号重复。 #pragma once 仅防止在编译同一个源文件时多次包含 header,但在编译另一个源代码时仍然可以包含第二次。
您的 test
对象违反了单一定义规则。
#pragma once
使定义不会在相同的 编译单元中多次出现(阅读:相同的*. cpp 文件),但不会出现在 不同的 编译单元中(读取:不同的 *.cpp 文件)。
解决此问题的一种方法是将对象转换为函数内的静态本地对象,并使其可通过引用访问:
header.h:
// ...
namespace ActorFactory {
// ...
typedef std::map<std::string, Actor*(*)()> class_map;
class_map& test();
}
test.cpp:
#include "header.h"
namespace ActorFactory {
// ...
class_map& test() {
static class_map test = {
{ "Camera", &createInstance<Camera> }
{ "Mesh", &createInstance<Mesh> };
return test;
}
}
这也是针对所谓的 static initialization order fiasco 的故障安全保证,并为您提供惰性初始化(与这个小对象无关紧要)。
您可以通过使用 new
分配对象并且从不删除它来使整个事情更加安全(面对销毁顺序问题),但函数应该仍然 return 参考文献:
namespace ActorFactory {
// ...
class_map& test() {
static class_map* test = new class_map {
{ "Camera", &createInstance<Camera> }
{ "Mesh", &createInstance<Mesh> };
return *test;
}
}
阅读上面链接的常见问题解答以获取所有详细信息。
在任何情况下,客户端代码都可以通过 test()
而不是 test
访问对象。