产生原因
自己在学习namespace时,参照C++ plus一书写了基本相同的代码,分别定义了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 void showPerson(struct Person& rp);
}namespace debts
{struct Debt;static void getDebt(struct Debt& rd);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)
结论
结合网络相关文章,我认采纳的错误原因函数产生了二义性。当然,网上各种文章对此错误的原因分析分别为:
- #program once只能识别一次,第二次包含再遇到#program once就会判定错误(可能,但是个人仁伟既然有program once用法,vs怎末可能第二次识别的时候错误了呢)
- .h文件不能多次包含(实际因为prgrame once不会有这种情况)
- .mian不能多处定义(不会有这种非常低级的错误)
- 变量或函数多次定义(可能)
- 强符号不能多次定义(又多了解了一点)
当然,上面的说法可能大家实际需要的情况不一样,有道理但是并不适用于我的场景,我感觉比较合理的说法是:函数多次定义,应为函数首先在Scource文件中进行了定义,在h文件中进行了声明,但是在执行main时又包括了一次source,导致函数产生二义性,根本原因是函数的特征符相同,也就是编译器首先进行函数重载,但是发现特征符相同,所以报二次定义。