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;
}