1. 为什么会有名称空间
如果有2个库,都用了同名的函数,或者有同名的两个类,所以出现了名称空间的方式
2. 定义命名空间
命名空间的定义使用关键字 namespace,后跟命名空间的名称,如下所示:
namespace namespace_name {
// 代码声明
}
为了调用带有命名空间的函数或变量,需要在前面加上命名空间的名称,如下所示:
name::code; // code 可以是变量或函数
3. 一个简单演示命名空间的例子
test.cpp
#include <iostream>
using namespace std;
namespace first_space {
void func() {
cout << "first_space" << endl;
}
}
namespace second_space {
void func() {
cout << "second_space" << endl;
}
}
int main(int argc, char *argv[])
{
first_space::func();
second_space::func();
return 0;
}
程序的运行结果!
lydia@lydia:~/sgy/c++_learn/namespace$ ./test
first_space
second_space
4. using声明和using编译指令
您可以使用 using namespace指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称
using声明将特定的名称添加到它所属的声明区域中。
using 声明的样子
using Jill::fetch;
例如main()中的using 声明Jill::fetch将fetch加入到mian()定义的声明区域中
using编译指令使所有的名称都可用,它使名称空间中的所有名称都可用,而不需要作用域解析运算符
using namespace Jack;
5. using编译指令和using 声明的区别
下面这个例子很能说明他们之间的区别
5.1 using编译指令放在全局声明区域,编译能通过,但是访问同名变量会有歧义,报错
test.cpp
只是使用using namespace 编译指令,不使用这个test_var变量的话编译是能够通过的!
#include <iostream>
using namespace std;
namespace first_space {
int test_var = 2;
}
int test_var = 9;
using namespace first_space;
int main(int argc, char *argv[])
{
//cout << "test_var:" << test_var << endl;
return 0;
}
编译的结果,并没有报错!
lydia@lydia:~/sgy/c++_learn/namespace$ g++ -o test test.cpp
lydia@lydia:~/sgy/c++_learn/namespace$
使用这个变量就会出现歧义,因为不知道使用的是全局变量test_var,还是namespace first_space 里的test_var!
test.cpp
#include <iostream>
using namespace std;
namespace first_space {
int test_var = 2;
}
int test_var = 9;
using namespace first_space;
int main(int argc, char *argv[])
{
cout << "test_var:" << test_var << endl;
return 0;
}
编译的执行结果!会出现变量的歧义
lydia@lydia:~/sgy/c++_learn/namespace$ g++ -o test test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:12:28: error: reference to ‘test_var’ is ambiguous
cout << "test_var:" << test_var << endl;
^~~~~~~~
test.cpp:8:5: note: candidates are: int test_var
int test_var = 9;
^~~~~~~~
test.cpp:5:9: note: int first_space::test_var
int test_var = 2;
^~~~~~~~
5.2 using编译指令放在函数内部(如main函数内)声明区域,编译能通过,但是访问同名变量会有歧义,报错
结果是一样的!
5.3 using声明放在全局声明区域,编译不能通过!
test.cpp
#include <iostream>
using namespace std;
namespace first_space {
int test_var = 2;
}
int test_var = 9;
using first_space::test_var;
int main(int argc, char *argv[])
{
//cout << "test_var:" << test_var << endl;
return 0;
}
编译的结果!
lydia@lydia:~/sgy/c++_learn/namespace$ g++ -o test test.cpp
test.cpp:9:20: error: ‘test_var’ is already declared in this scope
using first_space::test_var;
^~~~~~~~
lydia@lydia:~/sgy/c++_learn/namespace$
5.4 using声明放在函数内部声明区域,编译能通过,使用的是局部变量!
test.cpp
#include <iostream>
using namespace std;
namespace first_space {
int test_var = 2;
}
int test_var = 9;
int main(int argc, char *argv[])
{
using first_space::test_var;
cout << "test_var:" << test_var << endl;
return 0;
}
执行的结果
lydia@lydia:~/sgy/c++_learn/namespace$ ./test
test_var:2
lydia@lydia:~/sgy/c++_learn/namespace$
使用的是名称空间中的变量!
引用全局变量可以使用**::var的方法**
using编译指令会使名称空间中所有的名称可用。但是不会引起报错,如果名称空间中有同名的变量。
6. 名称空间的嵌套和名称空间的别名
6.1 嵌套名称空间的格式
namespace elements
{
namespace fire
{
int flame;
}
float water;
}
namespace myth
{
using Jill::fetch;
using namespace elements;
using std::cout;
}
假设要访问fetch,有两种访问的方式
- myth::fetch;
- Jill::fetch;
using namespace myth 相当于导入了名称空间 myth和elements
相当于
using namespace myth;
using namespace elements;
6.2 名称空间的别名
6.3 未命名的名称空间
未命名的名称空间可以当做static来使用,看一下面的这个具体的例子。
6.4 具体的一个名称空间的比较详细的使用例子
#include <iostream>
#include <string>
// create the pers and debts namespaces
namespace pers
{
struct Person
{
std::string fname;
std::string lname;
};
void getPerson(Person &);
void showPerson(const Person &);
}
namespace debts
{
//using namespace std;
using namespace pers;
struct Debt
{
Person name;
double amount;
};
void getDebt(Debt &);
void showDebt(const Debt &);
double sumDebts(const Debt ar[], int n);
}
namespace pers
{
using std::cout;
using std::cin;
void getPerson(Person & rp)
{
cout << "Enter first name: ";
cin >> rp.fname;
cout << "Enter last name: ";
cin >> rp.lname;
}
void showPerson(const Person & rp)
{
std::cout << rp.lname << ", " << rp.fname;
}
}
namespace debts
{
void getDebt(Debt & rd)
{
getPerson(rd.name);
std::cout << "Enter debt: ";
std::cin >> rd.amount;
}
void showDebt(const Debt & rd)
{
showPerson(rd.name);
std::cout <<": $" << rd.amount << std::endl;
}
double sumDebts(const Debt ar[], int n)
{
double total = 0;
for (int i = 0; i < n; i++)
total += ar[i].amount;
return total;
}
}
void other(void);
void another(void);
int main(void)
{
using debts::Debt;
using debts::showDebt;
Debt golf = { {"Benny", "Goatsniff"}, 120.0 };
showDebt(golf);
other();
another();
// std::cin.get();
// std::cin.get();
return 0;
}
void other(void)
{
using std::cout;
using std::endl;
using namespace debts;
Person dg = {"Doodles", "Glister"};
showPerson(dg);
cout << endl;
Debt zippy[3];
int i;
for (i = 0; i < 1; i++)
getDebt(zippy[i]);
for (i = 0; i < 1; i++)
showDebt(zippy[i]);
cout << "Total debt: $" << sumDebts(zippy, 3) << endl;
return;
}
void another(void)
{
using pers::Person;;
Person collector = { "Milo", "Rightshift" };
pers::showPerson(collector);
std::cout << std::endl;
}