C++ 命名空间
1. 什么是命名空間
在編程語言中,命名空間是一種特殊的作用域,它包含了處于該作用域中的所有標示符,而且其本身也是由標示符表示的。命名空間的使用目的是為了將邏輯相關的標示符限定在一起,組成相應的命名空間,可使整個系統更加模塊化,最重要的是它可以防止命名沖突。就好比在兩個函數或類中定義相同名字的對象一樣,利用作用域標示符限定該對象是哪個類里定義的。
2. C++中的命名空間定義
在C++語言中,命名空間使用namespace來聲明,并使用{ }來界定命名空間的作用域,例如:
namespace foo{
int num=0;
}
3. C++中的std命名空間
std命名空間是C++中標準庫類型對象的命名空間。
在標準C++以前,都是用#include<iostream.h>這樣的寫法的,因為要包含進來的頭文件名就是iostream.h。標準C++引入了名字空間的概念,并把iostream等標準庫中的東東封裝到了std名字空間中,同時為了不與原來的頭文件混淆,規定標準C++使用一套新的頭文件,這套頭文件的文件名后不加.h擴展名,如iostream、string等等,并且把原來C標準庫的頭文件也重新命名,如原來的string.h 就改成cstring(就是把.h去掉,前面加上字母c),所以頭文件包含的寫法也就變成了#include <iostream>。
并不是寫了#include<iostream>就必須用using namespace std;我們通常這樣的寫的原因是為了一下子把std名字空間的東東全部暴露到全局域中(就像是直接包含了iostream.h這種沒有名字空間的頭文件一樣),使標準C++庫用起來與傳統的iostream.h一樣方便,但并不建議這樣做,因為使用using namespace std;的話就沒有起到命名空間的作用。再次回到了如同沒有涉及命名空間時,所有標示符都定義在全局作用于中的混亂情況,不利于程序員創建新對象。
如果不用using namespace std;使用標準庫時就得時時帶上名字空間的全名,如std::cout << "hello" << std::endl;
<iostream>和<iostream.h>是不一樣,前者沒有后綴,實際上,在編譯器include文件夾里面可以看到,二者是兩個文件,打開文件就會發現,里面的代碼是不一樣的。后綴為.h的頭文件c++標準已經明確提出不支持了,早些的實現將標準庫功能定義在全局空間里,聲明在帶.h后綴的頭文件里,c++標準為了和C區別開,也為了正確使用命名空間,規定頭文件不使用后綴.h。因此,當使用<iostream.h>時,相當于在c中調用庫函數,使用的是全局命名空間,也就是早期的c++實現;當使用<iostream>的時候,該頭文件沒有定義全局命名空間,必須使用namespace std;這樣才能正確使用cout。
如下寫法,則出錯
#include <iostream.h>
using namespace std;
 所以 要么寫成?
 #include <iostream>
using std::cout;
using std::cin;
using std::cerro;
要么寫成
#include <iostream.h>
當然最好是前種,因為后種情況如果遇到用戶定義的標示符在頭文件中已經定義,可能會導致錯誤,采用using namespace std也是如此。
4. 命名空間實際上是一個作用域
 例如:?
 在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();?
 }
5. 使用標準庫中標示符的方法
-  
使用標示符限定命名空間: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;的寫法引入了名空間的所有內容,這是一種簡單但不保險的做法,是標準庫組織不推薦這么做的。因為這樣引入了所有的組件函數名,相當于重新引發了名字空間泛濫的問題。為此,好的做法應該是第二種分別引入。
總結
                            
                        - 上一篇: 华为2014校园招聘的机试题目
 - 下一篇: 京东闪付额度是多少?限额怎么办?