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