C++名稱空間
名稱空間是C++為了防止寫程式時命名發送衝突而設計出來的,其實和文件夾類似,不同名稱空間下的名稱可以相同。
接觸過C++的人都應該對using namespace std
很熟悉,這就是大家最常見的名稱空間應用,叫做using編譯指令,其中std
是一個名稱空間的名字。
C++提供了兩種機制來簡化對名稱空間中名稱的使用:
- using聲明(例如:using std::cout)
- using編譯指令(例如:using namespace std)
先我們來了解聲明是名稱空間,看程式碼
#include <iostream>
namespace nsp {
int a = 0;
void hello()
{
std::cout << "Hello!" << std::endl;
}
}
int main()
{
std::cout << nsp::a << std::endl;
nsp::hello();
}
程式碼中定義了名稱空間 nsp,其中包含兩個名稱 a 和 hello,如果不使用 using 命令,那就只能用域解析運算符::
來進行使用了。
名稱空間相當於將一些名稱打包,然後給這個包取個名字,通過名稱空間的名字和域解析運算符::
就可以使用裡面的名稱了
使用 using 聲明,就是把裡面的一個名稱單獨取出來使用,如:`using nsp::hello’,要記住函數名稱後面不能加括弧
使用 using 編譯指令,就是把包給解開,使得所有名稱都可以使用,如:’using namespace nsp’
使用 using 指令後,名稱的可用範圍時從使用處起,到該作用域結束為止
例如如果是在函數里用,就是從使用位置開始到函數結束的位置,在這個範圍里可以直接使用釋放出來的名稱
::
還可以用於訪問被局部變數覆蓋了的全局變數,如test.cpp中程式碼,其中::x
表示的就是全局duoble型變數 x:
#include <iostream>
double x = 27.0;
void test(int a)
{
int x = a;
{
using std::cout;
char x = 'Q';
cout << "最內層x = " << x << "\n"
<< "全局::x = " << ::x << std::endl;
}
using std::endl;
std::cout << "中間層x = " << x << '\n' << endl;
}
下面是文件main.cpp的內容:
extern void test(int x); // extern 可以省略,不省略的好處是可以明確指出這是在外部文件定義的函數
namespace nsp {
int a = 7;
}
int main()
{
using namespace nsp;
test(a); // a 為 7
int a = 9;
test(a); // a 為 9
}
注意:使用 using 聲明後,不可在同一級別的作用域里再次聲明一樣的名稱,因為 using 聲明也相當於聲明,而 C++ 不允許在同一文件中重複聲明,不過可以在不同級別的作用域里再次聲明,一層花括弧就是更深一層的作用域。不過 using 編譯指令就沒有這個限制了,你還是可以重複聲明一次相同的名稱。
使用名稱空間還需要注意:
- 名稱空間可以嵌套,但不可以在程式碼塊中,例如在函數中定義名稱空間
- 同一名稱空間可分布在不同的文件中,也可以在同一文件的不同位置
- 要使用名稱空間中在其他文件里的變數或者函數,需要在本文件的名稱空間中聲明為外部變數,函數也一樣
如下面程式碼:
// test.cpp
#include <iostream>
namespace nsp
{
double x = 27.0;
void test(int a)
{
using namespace std;
cout << a << endl;
}
}
// main.cpp
namespace nsp {
int a = 7;
extern double x; // 必須加 extern 否則會報錯
extern void test(int); // 可省略 extern
}
namespace nsp {
int b = 8;
}
int main()
{
using namespace nsp;
test(a); // a 為 7
test(b); // b 為 8
int a = 9;
test(a); // a 為 9
test(x); // x 為 27
}
下面是使用頭文件的情況,一般在項目中都會把聲明放到頭文件中,然後再用同名稱的.cpp文件來進行實現
// test.h
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
namespace TEST
{
const double x = 27.0; // 溫馨提示:頭文件中不要有變數
void test(int);
}
#endif // TEST_H_INCLUDED
// test.cpp
#include <iostream>
#include "test.h"
namespace TEST
{
void test(int a)
{
using namespace std;
cout << a << endl;
}
}
// main.cpp
#include "test.h"
namespace TEST {
int a = 7;
}
namespace TEST {
int b = 8;
}
int main()
{
using namespace TEST;
test(a); // a 為 7
test(b); // b 為 8
int a = 9;
test(a); // a 為 9
test(x); // x 為 27
}
預編譯指令#include "test.h"
的作用其實就是將 test.h 文件中的內容替換掉這一行。
我是七進位,一個被編程耽誤的吉他手