Fork me on GitHub

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文件创建该函数的副本。

 

posted @   张一默  阅读(545)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示