C++std名稱空間詳解
- 什麼是名稱空間
在程式語言中,名稱空間是一種特殊的作用域,它包含了處於該作用域中的所有標示符,而且其本身也是由標示符表示的。名稱空間的使用目的是為了將邏輯相關的標示符限定在一起,組成相應的名稱空間,可使整個系統更加模組化,最重要的是它可以防止命名衝突。就好比在兩個函式或類中定義相同名字的物件一樣,利用作用域標示符限定該物件是哪個類裡定義的。
- C++中的名稱空間定義
在C++語言中,名稱空間使用namespace來宣告,並使用{ }來界定名稱空間的作用域,例如:
namespace foo{
int num=0;
}
- C++中的std名稱空間
std名稱空間是C++中標準庫型別物件的名稱空間。
在標準C++以前,都是用#include
#include <iostream.h>
using namespace std;
所以 要麼寫成
#include <iostream>
using std::cout;
using std::cin;
using std::cerro;
要麼寫成
#include <iostream.h>
當然最好是前種,因為後種情況如果遇到使用者定義的標示符在標頭檔案中已經定義,可能會導致錯誤,採用using namespace std也是如此。
- 名稱空間實際上是一個作用域
例如:
在x.h中的內容為
// x.h
namespace MyNamespace1
{
class MyClass
{
public:
void f();
private:
int m;
}
};
在y.h中的內容為
// y.h
namespace MyNamespace2
{
class MyClass
{
public:
void f();
private:
int m;
}
};
然後在z.cpp中引入x.h和y.h
// z.cpp
#include "x.h"
#include "y.h"
void z::f()
{
//宣告一個檔案x.h中類MyClass的例項x
MyNamespace1::MyClass x;
//宣告一個檔案x.h中類MyClass的例項x
MyNamespace2::MyClass y;
//呼叫檔案x.h中的函式f
x.f();
//呼叫檔案y.h中的函式f
y.f();
}
- 使用標準庫中標示符的方法
使用標示符限定名稱空間:
std::cout<<"Hello!"<<endl;
使用using std::cout;事先宣告:cout<<"Hello!"<<endl;
//分別引入,需要用哪個引用哪個,保證程式中名稱的唯一性
使用using naspace std宣告:cout<<"Hello!"<<endl;
//引入名字空間的所有內容,不推薦這樣寫
因為標準庫非常的龐大,所程式設計師在選擇的類的名稱或函式名時就很有可能和標準庫中的某個名字相同。所以為了避免這種情況所造成的名字衝突,就把標準庫中的一切都被放在名字空間std中。但這又會帶來了一個新問題。無數原有的C++程式碼都依賴於使用了多年的偽標準庫中的功能,他們都是在全域性空間下的。所以就有了<iostream.h>
和<iostream>
等等這樣的標頭檔案,一個是為了相容以前的C++程式碼,一個是為了支援新的標準。名稱空間std封裝的是標準庫的名稱,標準庫為了和以前的標頭檔案區別,一般不加”.h”
C++語言是從C語言發展起來的,因此有很多借鑑的地方。當C++語言推出但尚未標準化以前(98年才標準化),市場上已經有了很多版本的程式庫了,各庫林立,導致互相應用時出現了一個很難調和的難題,那就是命名衝突,又稱名空間氾濫。比如某個庫寫了個函式line(int x,int y);不巧另外一個庫又寫了個類class line;這下編譯器該匹配哪個呢?只好取決於哪個庫檔案先被引用到檔案中,並且把另外一個完全遮蔽掉。這顯然不是一個好的方法。在標準庫的產生過程中,這個問題被提了出來。為此,標準庫組織決定在標準庫中引入名空間的概念,所有標準庫的元件都在名空間std中定義,由使用者手動引入到程式中,這樣就讓編譯器知道,當遇到一個可能衝突的名稱時,以標準庫中定義的名稱為主,如果想用標準庫外定義的名稱,那程式設計師需要自己註明另外的名空間,從而達到消除名空間氾濫的目的。using namespace std;的寫法引入了名空間的所有內容,這是一種簡單但不保險的做法,是標準庫組織不推薦這麼做的。因為這樣引入了所有的元件函式名,相當於重新引發了名字空間氾濫的問題。為此,好的做法應該是第二種分別引入。