C++学习笔记1——链接器工具错误 LNK2005

对象中已定义的符号

多次定义了符号 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;
//}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值