对象中已定义的符号
多次定义了符号 symbol。
该错误之后为错误 LNK1169。
可能的原因和解决方案
通常,此错误意味着违反了唯一定义规则,该规则允许对给定对象文件中使用的任何模板、函数、类型或对象进行唯一定义,且允许在整个可执行文件中对外部可见对象或函数进行唯一定义。
以下是导致此错误的一些常见原因。
头文件定义变量时,可能会发生此错误。 例如,如果在项目的多个源文件中包含此头文件,会导致错误:
// LNK2005_global.h
int global_int; // LNK2005
可能的解决方案包括:
在头文件: extern int global_int; 中声明变量 extern,然后定义它并选择性地在唯一的源文件: int global_int = 17; 中进行初始化。 此变量现在是全局变量,可通过将其声明为 extern(例如,通过包含头文件)在任何源文件中使用。 对于必须是全局变量的变量,建议使用此解决方案,但良好的软件工程做法可以最大程度地减少全局变量。
将变量声明为 static:static int static_int = 17;。 这将定义的范围限制为当前对象文件,并允许多个对象文件拥有自己的变量副本。 不建议在头文件中定义静态变量,因为可能会与全局变量混淆。 建议将静态变量定义移动到使用它的源文件。
将变量声明为 selectany:__declspec(selectany) int global_int = 17;。 这会使链接器选择唯一定义以供所有外部引用使用,并丢弃其余定义。 组合导入库时,此解决方案有时很有用。 在其他情况下,不建议使用它来避免链接器错误。
头文件定义的函数不是 inline 时,可能会发生此错误。 如果将此头文件包含在多个源文件中,则会获得可执行文件中的函数的多个定义。
// LNK2005_func.h
int sample_function(int k) { return 42 * (k % 167); } // LNK2005
可能的解决方案包括:
将 inline 关键字添加到函数中:
// LNK2005_func_inline.h
inline int sample_function(int k) { return 42 * (k % 167); }
从头文件中删除函数正文,只留声明,然后在唯一的源文件中实现函数:
// LNK2005_func_decl.h
int sample_function(int);
// LNK2005_func_impl.cpp
int sample_function(int k) { return 42 * (k % 167); }
如果在头文件中的类声明之外定义成员函数,也会发生此错误:
// LNK2005_member_outside.h
class Sample {
public:
int sample_function(int);
};
int Sample::sample_function(int k) { return 42 * (k % 167); } // LNK2005
当前代码中遇到的就是这个问题:
template <typename T> class EnumParser
{
map<string, T> enumMap;
public:
EnumParser() {};
T ParseSomeEnum(const string& value)
{
typename map <string, T>::const_iterator iValue = enumMap.find(value);
if (iValue == enumMap.end())
throw runtime_error("");
return iValue->second;
}
};
EnumParser<Region>::EnumParser()
{
enumMap["mom"] = mom;
enumMap["po"] = po;
enumMap[""] = po;
}
在头文件类声明之外定义了成员函数,解决办法就是把成员函数移进类声明之中:
template <typename T> class EnumParser
{
map<string, T> enumMap;
public:
EnumParser()
{
enumMap["mom"] = mom;
enumMap["po"] = po;
enumMap[""] = po;
};
T ParseSomeEnum(const string& value)
{
typename map <string, T>::const_iterator iValue = enumMap.find(value);
if (iValue == enumMap.end())
throw runtime_error("");
return iValue->second;
}
};
//EnumParser<Region>::EnumParser()
//{
// enumMap["mom"] = mom;
// enumMap["po"] = po;
// enumMap[""] = po;
//}