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


    对象中已定义的符号

    多次定义了符号 symbol。

    该错误之后为错误 LNK1169。

    可能的原因和解决方案
    通常,此错误意味着违反了唯一定义规则,该规则允许对给定对象文件中使用的任何模板、函数、类型或对象进行唯一定义,且允许在整个可执行文件中对外部可见对象或函数进行唯一定义。

    以下是导致此错误的一些常见原因。

    头文件定义变量时,可能会发生此错误。 例如,如果在项目的多个源文件中包含此头文件,会导致错误:

    // LNK2005_global.h
    int global_int;  // LNK2005
    
    • 1
    • 2

    可能的解决方案包括:

    在头文件: 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
    
    • 1
    • 2

    可能的解决方案包括:

    将 inline 关键字添加到函数中:

    // LNK2005_func_inline.h
    inline int sample_function(int k) { return 42 * (k % 167); }
    
    • 1
    • 2

    从头文件中删除函数正文,只留声明,然后在唯一的源文件中实现函数:

    // LNK2005_func_decl.h
    int sample_function(int);
    
    • 1
    • 2
    // LNK2005_func_impl.cpp
    int sample_function(int k) { return 42 * (k % 167); }
    
    • 1
    • 2

    如果在头文件中的类声明之外定义成员函数,也会发生此错误:

    // LNK2005_member_outside.h
    class Sample {
    public:
        int sample_function(int);
    };
    int Sample::sample_function(int k) { return 42 * (k % 167); }  // LNK2005
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当前代码中遇到的就是这个问题:

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在头文件类声明之外定义了成员函数,解决办法就是把成员函数移进类声明之中:

    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::EnumParser()
    //{
    //	enumMap["mom"] = mom;
    //	enumMap["po"] = po;
    //	enumMap[""] = po;
    //}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    狂团KtAdmin框架正式免费开源发布,助力独立版SAAS系统快速开发!
    java-ssm-jsp-大学社团管理系统
    datawhale动手学大模型应用开发-第五章-系统评估与优化
    CentOS(4)——关于Linux软件下载时:amd64、x86、x86_64、arm64 的说明
    Java基础八股
    世界环境日 | 周大福用心服务推动减碳环保
    第十届全国大学生光电设计竞赛(西北区赛)经历
    Django DRF API(GET/POST/PUT)序列化和反序列化(一对多,多对多)demo-模型类序列化器ModelSerializer
    Docker部署ruoyi前后端分离项目 补充
    arcgis 批量删除Table中的某些Field
  • 原文地址:https://blog.csdn.net/Rye_dt/article/details/126565070