VS2022编译错误:链接器工具错误 LNK2005
产生原因
自己在学习namespace时,参照C++ plus“9.3.2 新的命名空间特性”一书写了基本相同的代码,分别定义了h文件和两个CPP文件,其中一个CPP用来定义变量,一个CPP用来跑main(void)。文件代码如下:
head.h文件
#pragma once #include<string> #include <iostream> namespace pers { struct Person; inline void getPerson(struct Person& rp);//编译错误的时候没有inline inline void showPerson(struct Person& rp); } namespace debts { struct Debt; static void getDebt(struct Debt& rd);//编译错误的时候没有static static void showDebt(struct Debt& rd); static double sumDebts(const struct Debt ar[], int n); }
source.cpp
#include "head.h" namespace pers { using namespace std; struct Person { std::string fname; std::string lname; }; //拿取名字 void getPerson(struct Person& rp) { cout << "Enter the first name: "; cin >> rp.fname; cout << "Enter the last name: "; cin >> rp.lname; } //展示名字 void showPerson(struct Person& rp) { cout << rp.fname << rp.lname << endl; } } namespace debts { using namespace pers; struct Debt { Person name; double amount; }; void getDebt(struct Debt &rd) { getPerson(rd.name);//debt类型 cout << "Enter debt: " << endl; cin >> rd.amount;//存放欠款 } void showDebt(struct Debt& rd) { showPerson(rd.name); cout << rd.amount << endl; } double sumDebts(const struct Debt ar[], int n) { double total=0.0; for (int i = 0; i < n; i++) total+= ar[i].amount; return total; } }
main.cpp
#include "source.cpp" #include "head.h" int main(void) { using debts::Debt; using debts::showDebt; struct Debt user = {{"zhang","wei"},123}; showDebt(user); return 0; }
编译错误现象
解决过程
1、尝试将source.cpp文件改为.h文件,编译错误
2、尝试将main.cpp文件中的.h文件包含去除,避免二次包含,编译错误
3、迫不得已按照官方的处理办法进行了static,但个人感觉inline内联更好一点,至少占用的栈资源能少一点。链接器工具错误和警告 (LNKxxxx)
结论
结合网络相关文章,我认采纳的错误原因函数产生了二义性。当同时,网上各种文章对此错误的原因分析分别为:
- #ppragma once只能识别一次,第二次包含再遇到#program once就会判定错误(可能,但是个人仁伟既然有#pragma once用法,vs怎末可能第二次识别的时候错误了呢)
- .h文件不能多次包含(实际因为#pragma once不会有这种情况)
- .mian不能多处定义(不会有这种非常低级的错误)
- 变量或函数多次定义(可能)
- 强符号不能多次定义(又多了解了一点)
当然,上面的说法可能大家实际需要的情况不一样,有道理但是并不适用于我的场景,我感觉比较合理的说法是:函数多次定义,应为函数首先在Scource文件中进行了定义,在h文件中进行了声明,但是在执行main文件时又包括了一次source文件,导致函数产生二义性,根本原因是函数的特征符相同,也就是编译器首先进行函数重载,但是发现特征符相同,所以报二次定义。
可以采用inline内联进行文本替换,当然依旧按值传递;也可以采用static声明内部链接性,允许每一个包含头文件的cpp文件创建该函数的副本。
本文来自博客园,作者:{张一默},转载请注明原文链接:https://www.cnblogs.com/YiMo9929/p/16750483.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理