C++頭文件和std命名空間(精闢)

C++是在C語言的基礎上開發的,早期的 C++ 還不完善,不支持命名空間,沒有本身的編譯器,而是將 C++ 代碼翻譯成C代碼,再經過C編譯器完成編譯。這個時候的 C++ 仍然在使用C語言的庫,stdio.h、stdlib.h、string.h 等頭文件依然有效;此外 C++ 也開發了一些新的庫,增長了本身的頭文件,例如:html

  • iostream.h:用於控制檯輸入輸出頭文件。
  • fstream.h:用於文件操做的頭文件。
  • complex.h:用於複數計算的頭文件。

和C語言同樣,C++ 頭文件仍然以.h爲後綴,它們所包含的類、函數、宏等都是全局範圍的。 ios

後來 C++ 引入了命名空間的概念,計劃從新編寫庫,將類、函數、宏等都統一歸入一個命名空間,這個命名空間的名字就是std。std 是 standard 的縮寫,意思是「標準命名空間」。 程序員

可是這時已經有不少用老式 C++ 開發的程序了,它們的代碼中並無使用命名空間,直接修改原來的庫會帶來一個很嚴重的後果:程序員會由於不肯花費大量時間修改老式代碼而極力反抗,拒絕使用新標準的 C++ 代碼。 函數

C++ 開發人員想了一個好辦法,保留原來的庫和頭文件,它們在 C++ 中能夠繼續使用,而後再把原來的庫複製一份,在此基礎上稍加修改,把類、函數、宏等歸入命名空間 std 下,就成了新版 C++ 標準庫。這樣共存在了兩份功能類似的庫,使用了老式 C++ 的程序能夠繼續使用原來的庫,新開發的程序可使用新版的 C++ 庫。 spa

爲了不頭文件重名,新版 C++ 庫也對頭文件的命名作了調整,去掉了後綴.h,因此老式 C++ 的iostream.h變成了iostreamfstream.h變成了fstream。而對於原來C語言的頭文件,也採用一樣的方法,但在每一個名字前還要添加一個c字母,因此C語言的stdio.h變成了cstdiostdlib.h變成了cstdlib.net

須要注意的是,舊的 C++ 頭文件是官方所反對使用的,已明確提出再也不支持,但舊的C頭文件仍然可使用,以保持對C的兼容性。實際上,編譯器開發商不會中止對客戶現有軟件提供支持,能夠預計,舊的 C++ 頭文件在將來數年內仍是會被支持。 翻譯

下面是我總結的 C++ 頭文件的現狀:
1) 舊的 C++ 頭文件,如 iostream.h、fstream.h 等將會繼續被支持,儘管它們不在官方標準中。這些頭文件的內容不在命名空間 std 中。 code

2) 新的 C++ 頭文件,如 iostream、fstream 等包含的基本功能和對應的舊版頭文件類似,但頭文件的內容在命名空間 std 中。htm

注意:在標準化的過程當中,庫中有些部分的細節被修改了,因此舊的頭文件和新的頭文件不必定徹底對應。

3) 標準C頭文件如 stdio.h、stdlib.h 等繼續被支持。頭文件的內容不在 std 中。 教程

4) 具備C庫功能的新C++頭文件具備如 cstdio、cstdlib 這樣的名字。它們提供的內容和相應的舊的C頭文件相同,只是內容在 std 中。

能夠發現,對於不帶.h的頭文件,全部的符號都位於命名空間 std 中,使用時須要聲明命名空間 std;對於帶.h的頭文件,沒有使用任何命名空間,全部符號都位於全局做用域。這也是 C++ 標準所規定的。

不過現實狀況和 C++ 標準所指望的有些不一樣,對於原來C語言的頭文件,即便按照 C++ 的方式來使用,即#include <cstdio>這種形式,那麼符號能夠位於命名空間 std 中,也能夠位於全局範圍中,請看下面的兩段代碼。

1) 使用命名空間 std:

  1. include <cstdio>

  2. int main(){
  3. std::printf("http://c.biancheng.net\n");
  4. return 0;
  5. }

2) 不使用命名空間 std:

  1. include <cstdio>

  2. int main(){
  3. printf("http://c.biancheng.net\n");
  4. return 0;
  5. }

這兩種形式在 Microsoft Visual C++ 和GCC下都可以編譯經過,也就是說,大部分編譯器在實現時並無嚴格遵循C++標準,它們對兩種寫法都支持,程序員可使用 std 也能夠不使用。

第 1) 種寫法是標準的,第 2) 種不標準,雖然它們在目前的編譯器中都沒有錯誤,但我依然推薦使用第 1) 種寫法,由於標準寫法會一直被編譯器支持,非標準寫法可能會在之後的升級版本中再也不支持。

使用C++的頭文件

雖然 C++ 幾乎徹底兼容C語言,C語言的頭文件在 C++ 中依然被支持,但 C++ 新增的庫更增強大和靈活,請讀者儘可能使用這些 C++ 新增的頭文件,例如 iostream、fstream、string 等。

前面幾節咱們使用了C語言的格式輸出函數 printf,引入了C語言的頭文件 stdio.h,將C代碼和 C++ 代碼混合在了一塊兒,我不推薦這樣作,請儘可能使用 C++ 的方式。下面的例子演示瞭如何使用 C++ 庫進行輸入輸出:

  1. include <iostream>

  2. include <string>

  3. int main(){
  4. //聲明命名空間std
  5. using namespace std;
  6. //定義字符串變量
  7. string str;
  8. //定義 int 變量
  9. int age;
  10. //從控制檯獲取用戶輸入
  11. cin>>str>>age;
  12. //將數據輸出到控制檯
  13. cout<<str<<"已經成立"<<age<<"年了!"<<endl;
  14. return 0;
  15. }

運行結果:
C語言中文網↙
6↙
C語言中文網已經成立6年了!

string 是 C++ 中的字符串類,初學者能夠將 string 看作一種內置的數據類型,就像 int、float 等,能夠用來定義變量。cin 用於從控制檯獲取用戶輸入,cout 用於將數據輸出到控制檯,下節咱們會詳細講解。

讀者暫時不須要深刻了解這段代碼的細節,只須要留意using namespace std;,它聲明瞭命名空間 std,後續若是有未指定命名空間的符號,那麼默認使用 std,代碼中的 string、cin、cout 都位於命名空間 std。

在 main() 函數中聲明命名空間 std,它的做用範圍就位於 main() 函數內部,若是在其餘函數中又用到了 std,就須要從新聲明,請看下面的例子:

  1. include <iostream>

  2. void func(){
  3. //必須從新聲明
  4. using namespace std;
  5. cout<<"http://c.biancheng.net"<<endl;
  6. }
  7. int main(){
  8. //聲明命名空間std
  9. using namespace std;
  10. cout<<"C語言中文網"<<endl;
  11. func();
  12. return 0;
  13. }

若是但願在全部函數中都使用命名空間 std,能夠將它聲明在全局範圍中,例如:

  1. include <iostream>

  2. //聲明命名空間std
  3. using namespace std;
  4. void func(){
  5. cout<<"http://c.biancheng.net"<<endl;
  6. }
  7. int main(){
  8. cout<<"C語言中文網"<<endl;
  9. func();
  10. return 0;
  11. }

不少教程中都是這樣作的,將 std 直接聲明在全部函數外部,這樣雖然使用方便,但在中大型項目開發中是不被推薦的,這樣作增長了命名衝突的風險,我推薦在函數內部聲明 std。

不過爲了方便,本教程仍是忍不住違反了原則,後面有不少代碼都在全局範圍內聲明瞭 std。

相關文章
相關標籤/搜索