ZWeily的小品文(四)C++入門教程(3) (轉)
“師傅,能不能幫我過來看看?”
一聽這個就知道,我那個“好”徒弟Young又用她那種極有“磁性”的聲音在召喚我,一定是遇到了什麼問題,搞不定了。
“別叫我師傅,這樣感覺我很老一樣,還是叫我Weily吧。”我一邊說,一邊走過去,一看,她開著一個,似乎是在寫。仔細一看,原來在最基本、最著名的那個Hello World啊,呵呵,我鼻樑上的眼鏡可不是擺設用的,我也看出問題所在了。
“有什麼問題啊?”我故意裝作什麼都不知道的樣子。
“恩……我這個程式無法執行,我也不知道錯在哪裡,編譯不透過,老是報錯,而且,我這個程式是完全按照書上打的呀,應該沒錯的呀!可是就是……”
“喔?讓我看看。”我裝模作樣地湊過去看螢幕,螢幕上的程式是這樣的:
#include
int main( )
{
cout < return 0;
}
Young還把一本書拿到我面前,的確,那本書上的程式和螢幕上的一模一樣。
“你看,我沒打錯吧?”Young一臉無辜的樣子,難得看到她這樣,這個表情看上去楚楚可憐,與平時調皮的Young截然不同。
“你別急,我知道了。先提醒你一點,就是別迷信權威和書本,任何人都有犯錯的時候,這是一個優秀的程式設計師應該具有的素質。這個問題麼,讓我一點點來講給你聽。你先看看報的錯是什麼錯,記住,一個優秀的程式設計師能充分利用編譯器的查錯能力,並且,能從編譯器給出的錯誤資訊裡判斷出錯誤所在,所以,要學會讀懂出錯資訊,這是我對你的最基本的要求。”
“喔!它報的錯誤是’cout’: undeclared identifier。這個我以前在學C的時候見過。就是當我的程式裡使用了一個沒有宣告過的變數的時候,就會產生這種錯誤。”
“完全正確!你已經說出了錯誤的原因了。”
“啊?可是cout應該是在頭iostream裡面已經引入我這個程式了啊,那麼就不應該沒有宣告過啊?”Young又一次陷入了迷茫。
“其實這個問題牽涉到C++裡面的一個特性,就是關於名字空間(namespace)的作用。”
“namespace?……”
“讓我們還是從你這個程式看起。cout是一個ostream,也就是一個輸出流物件。它的確在iostream中定義了。但是,它的全稱應該寫成std::cout。這個std就是一個namespace,所有標準庫裡的東西都被封裝在std這個namespace裡。所以,編譯器在這裡就不能認出cout,因為它不在全域性名字空間裡。”
“那是不是我只要把cout改成std::cout就可以了啊?”
“恩,這樣改動後就能用了。不過這個問題就像孔乙己的那個茴香豆的茴字的四種寫法一樣,這個問題的解決方法也有四種解決方法。”
“四種?那另外三種是什麼?快告訴我啊!”看來我這個比喻引起了Young的興趣。
“第一種,就是將std這個名字空間引入全域性名字空間。這個方法只要在全域性裡,也就是任何一個之外,當然,最好放放在預處理之後,任何一個函式之前,這樣,任何一個函式里都可以直接使用std這個namespace裡面的東西,就像使用全域性物件一樣。例如你這個程式,就能改成這樣。”
#include
using namespace std; //引入std這個namespace
int main( )
{
cout < return 0;
}
“這個程式就能透過編譯,而且其他的標準庫裡的東西,也可以像這裡的cout一樣,直接使用。”
“喔!那麼這個方法不是很方便嗎?也不容易出錯啊!”
“並不是這樣。其實這麼做了之後,std這個namespace就失去了它存在的意義了。C++裡引入namespace的目的就是為了避免汙染全域性名字空間,簡單地說,就是為了避免和減少命名衝突。一旦一個程式寫大了,就很難避免重名,特別是多人合作的情況下。過去C中的解決方法只有靠人為的注意,並且加長名字,以避免重名。這樣做會使得一些名字看上去沒有意義或者難以理解,而程式設計師在寫程式的時候,也受這個問題的限制,不能自由地命名自己使用的變數或者函式。而有了namespace就不存在這些問題了,這就是C++引入namespace這個概念所帶來的便利。當然,這也使得C++裡很多名字看上去特別長。”
“喔,原來如此!本來我還準備以後就一直這麼用呢!”
“接下來我們討論第二種解決方案。這個方案和前面一種類似,也是引入名字空間,只是,它只引入需要的一部分。就像這個程式,我們只需要cout這個物件,所以,我們只需將std中的cout引入就可以了。就像這樣。”
#include
using std::cout;
int main( )
{
cout < return 0;
}
“喔,原來還可以這樣啊!這樣就可以避免了全部引入所帶來的汙染名字空間的問題了。那最後一種呢?”
“最後一種解決方法更簡單,但是,我先要你注意,這個方法今天看過就算了,不用去記住它,更不要使用它。先讓我們來看看用了這個方案的程式是什麼樣子的。”
#include
int main( )
{
cout < return 0;
}
“這個方法的程式看上去似乎最簡短啊。對了,這個標頭檔案的問題也是我一直想問你的問題。我記得原來C裡面的那些標準庫的標頭檔案都是以.h結尾的啊,為什麼C++的標準庫的標頭檔案都沒有.h啊?”
“你能注意到這點很好,說明你在看書和寫程式的時候還在用腦子思考,並且能注意到許多人往往會忽視的細節問題。其實有.h這個字尾的標頭檔案和沒有.h的標頭檔案的最大的區別也在於namespace,有.h的標頭檔案裡的元素都是暴露在全域性中的,也就是沒有std這個namespace。而沒有.h的標頭檔案中的元素都是被封裝在std這個namespace中的。其實C++標準委員會早就去掉了標準庫裡每個標頭檔案的.h字尾,只是編譯器的生產廠商為了向前相容,為了能讓在標準出臺之前的程式都能用,於是仍然提供了.h的標頭檔案。記住,這些有.h的標頭檔案都不在C++標準之內,這也是我叮囑你不要去使用它的原因。還有一點,就是原來C中的那些標準庫標頭檔案,其實也存在相應的C++版本的,它們的命名規則很簡單,就是以c開頭,後面跟上原來的檔名,但是都沒有.h這個字尾。並且,其中的元素也都被封裝在std中了。”
“喔,原來還有這麼一個淵源啊!”
“是的。C++的發展過程中有很多類似的決策和選擇,現在標準裡定義的那些東西,都是專家們經過深思熟慮後才決定的,其中很多選擇和決定都有著它的道理,這個你有興趣的話可以去看看《The Design and Evolution of C++》這本書,它能告訴你C++為什麼是現在這樣的。其實因為C++有它的一套設計思想和設計哲學,標準庫裡的東西在設計上都符合這個思想,並且都保持著高效、的原則,所以,在你的程式中儘量地使用標準庫已經提供的東西,這樣你的程式碼將更為簡短、易讀,也更為安全可靠。記住這個原則。”
“恩,我記住了,並且以後會注意的。”
“好了,今天就講這些吧,關於標準庫的其他方面,以後我還會提起的。”
“好的,謝謝師傅!”
“和你說過多少遍了啊,別叫我師傅,我連女朋友都還沒有呢,我怕越叫越老的。就像記住我和你說的那些原則一樣,記住以後叫我Weily,別叫師傅!”
“遵命!師……”
“!”
“不是啦,我沒叫你師傅,我只是說‘是’”Young還是依舊那麼調皮。
“好啦,以後注意點。繼續寫你的程式,看你的書吧。”
“好的,Weily。今天多謝你了!”
“不用客氣啦,誰叫Solmyr把你交給了我呢……”
說完,回到自己的位子上,看著桌上那杯已經涼掉了的紅茶,哎……
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993227/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ZWeily的小品文(二)C++入門教程(1) (轉)C++
- ZWeily的小品文(三)C++入門教程(2) (轉)C++
- ZWeily的小品文(五)C++入門教程(4) (轉)C++
- ZWeily的小品文(一)MFC中的檔案讀寫問題 (轉)
- linux入門教程(3)(轉)Linux
- C++入門教程C++
- C++入門教程(3):語句和縮排C++
- 最適合入門的 Laravel 入門教程 (四)Laravel
- C++入門解惑(3)——初探指標(下) (轉)C++指標
- Solmyr 的小品文系列之四:物件計數(下) (轉)物件
- 遊戲製作詳解自----OpenGL入門教程(四)(轉)遊戲
- GRUB入門教程(轉)
- Visual C++/MFC入門教程C++
- Struts快速入門(四) (轉)
- Java入門教程四(字串處理)Java字串
- Metal入門教程(四)灰度計算
- C++入門教程(9):while 語句C++While
- C++入門教程(11):呼叫函式C++函式
- C++ 入門防爆零教程(上冊)C++
- scrapy入門教程3:scrapy的shell命令
- Vue3快速入門教程Vue
- Unity3D開發入門教程(四)——用Lua實現元件Unity3D元件
- C++入門(3):C++開發環境搭建C++開發環境
- C++入門教程(14):過載函式C++函式
- C++入門教程(12):定義函式C++函式
- C++入門教程之二:變數C++變數
- 轉:區塊鏈入門教程區塊鏈
- linux入門教程(2)(轉)Linux
- Internet worm入門教程 (轉)Worm
- [轉]Systemd 入門教程:命令篇
- Redux 入門教程(3):React-Redux 的用法ReduxReact
- 《Flask 入門教程》第 3 章:模板Flask
- D3入門教程翻譯
- Unity3D開發入門教程(二)—— Lua入門Unity3D
- 微信小程式入門教程之四:API 使用微信小程式API
- MVC5+EF6 入門完整教程四MVC
- Android Studio NDK 入門教程(3)--Java與C++之間的型別簽名AndroidJavaC++型別
- JDBCTM 指南:入門3 - DriverManager (轉)JDBC