原創(chuàng)|行業(yè)資訊|編輯:郝浩|2014-12-18 13:59:54.000|閱讀 7363 次
概述:學習和使用過C++的人幾乎都曾經(jīng)聽說過下面的五個關(guān)于C++的觀點,并且對這些話篤信不已,那么真實的情況是怎么樣的呢?本文的作者——C++之父Bjarne Stroustrup將會對這些觀點作逐一回擊。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
以下的這五個觀點盛行于C++多年:
如果你還對這些觀點深信不已,那么這篇文章可以給你一些重新認識。這些觀點在特定的時間對于某些人、某些工作來說是正確的。但是對于今天的C++,隨著ISO C++11標準的編譯器和工具的廣泛使用,這些觀點都需要被重新認識。
接下來,我們將會對這些觀點進行逐一反駁。
這不對,事實上對于基礎(chǔ)編程的學習來說C++比C語言容易的多。
C語言雖然幾乎可以認為是C++的子集,但對初學者來說卻不是最容易學習的。因為C語言缺乏標記支持和類型安全,并且對于簡化簡單任務(wù)來說C++的標準庫更加易于使用。
比如,對于一個非常簡單的用于描述郵件地址格式的函數(shù):
它可以被這樣使用:
而C語言中需要明確的字符操作和明確的內(nèi)存管理:
然后,它需要被這樣使用:
相比之下,哪種版本更加容易學習?哪種語言更加有效率?很顯然是C++了,因為它不需要計算參數(shù)字符,不需要為簡短的字符串分配動態(tài)內(nèi)存。
關(guān)于“C語言優(yōu)先學習”的觀點并非來自少部分人的認識。傳授這種典型觀點的老師主要有以下幾個方面原因:
然而,C語言并不是作為優(yōu)先學習的最簡單和有用的C++子集。當你知道足夠多的C++知識后學習C語言則會非常容易。這種學習方式可以有效減輕從C到C++學習時在認識和技術(shù)上的困難。
對于現(xiàn)代C++的教學方法,可以參見我的著作:Programming: Principles and Practice Using C++。它甚至在有一章的結(jié)尾處展示了如何學習使用C語言。這種教學方法在幾所大學的數(shù)以萬計學生中使用,非常的成功。它的第二版是使用C++11和 C++14來讓學習變得更加容易。
C++11標準使C++更容易被初學者接受,例如,這里是一個元素序列已初始化的vector標準庫:
在C++98中,我們只能初始化數(shù)組和列表。在C++11中,我們可以定義一個包含有{}和需要的任何類型的初始化列表的構(gòu)造函數(shù)。
我們可以通過for循環(huán)的范圍來遍歷vector:
對于v的任何一個元素都會調(diào)用一次test()。
for循環(huán)的范圍可以遍歷任何序列,因此我們可以通過直接使用初始化列表來簡化示例。
C++11的目的是使簡單的事情變得簡單。代碼的簡單化并沒有以性能降低為代價。
不對。C++支持面向?qū)ο蠛推?它編程風格,它并不僅限于“面向?qū)ο?rdquo;這個狹隘的觀點。它支持一個綜合的編程技術(shù),包括面向?qū)ο蠛头盒途幊獭MǔR粋€問題的最佳方式需要比較多種類型。最佳,在這里指的是時間最短、最易于理解、最有效率和最易于維護等等。
“C++是一門面向?qū)ο蟮恼Z言”的觀點使人們在除非需要擁有許多虛擬(多態(tài)運行)函數(shù)的巨大類層次結(jié)構(gòu)時才會考慮使用它。而這種用法對于許多問題來說是不合適的。這個觀點也會導(dǎo)致另外一些人指責C++的面向?qū)ο蟛⒉患兇狻.吘梗绻?ldquo;好”和“面向?qū)ο?rdquo;劃上等號的話,C++還包含了其它被認為是“不好”的非面向?qū)ο蟮臇|西。這種觀點產(chǎn)生的兩種認識都會導(dǎo)致人們放棄學習C++。(譯者注:作者表達的意思就是把C++比作是一個賣包子和賣米線的餐館。將C++認作是包子鋪會讓人產(chǎn)生2種誤會,其一,路過的人會以為這里只賣包子,不賣其它的;其二,愛吃包子的人會認為包子鋪還賣米線,這包子一定做得不專業(yè))
舉個例子:
它面向?qū)ο髥幔慨斎唬鼑乐匾蕾嚢摵瘮?shù)的類層次結(jié)構(gòu)。它是泛型編程嗎?當然是,它嚴重依賴于參數(shù)化容器(vector)和泛型函數(shù)for_each。它是函數(shù)式編程嗎?在一定程度上是,它使用了匿名函數(shù)(由[]構(gòu)造)。那么它到底是什么?它是現(xiàn)代C++:C++11。
我同時使用了for循環(huán)和標準庫算法for_each只是為了展示其特性。在實際代碼中,我只會使用其中的一個循環(huán)。
你想讓上面那段代碼更通用嗎?因為畢竟它只適用于vector指針的Shape基類。那么對于列表和內(nèi)置數(shù)組呢?對于象shared_ptr和unique_ptr這樣的“智能指針”(資源管理指針)呢?對于沒有調(diào)用Shape類的對象能夠使用draw()和rotate()么?可以這樣來做:
你可以使用這段程序?qū)θ魏涡蛄袕念^到尾進行遍歷。這是一個C++風格的標準庫算法。我使用了auto來避免必須為“象Shape類這樣的對象”的接口類型命名。這是C++11的特性,它的含義是“使用被用于初始化的表達式的類型”。所以由for循環(huán)中p的類型就能決定這是什么類型的對象。這種使用auto表示匿名函數(shù)參數(shù)類型的方法是現(xiàn)已廣泛使用的一個C++14新特性。
如下圖所示:
在這里我假定Blob是包含了操作函數(shù)draw()和rotate()的圖形化類型,而Container是容器類型。標準庫list(std::list)擁有成員函數(shù)begin()和end(),用于幫助用戶遍歷元素的序列。這是很好很經(jīng)典的面向?qū)ο缶幊獭5牵偃缛萜鞑恢С諧++標準關(guān)于遍歷半開序列[b:e)的概念呢?假如庫里面沒有begin()和end()成員函數(shù)呢?或者,由于沒有容器一類的東西因此無法遍歷。對于這些情況,我們可以用適當?shù)恼Z義來定義獨立的begin()和end()。標準庫提供了C語言風格的數(shù)組,因此如果容器是C語言風格的數(shù)組,問題就迎刃而解了——而C語言風格的數(shù)組非常常見。
來看看一個更難點的例子,假如容器保留了對象的指針,并且有一個用于訪問和遍歷的不同模型呢?比如,你會訪問到象下面的這個容器:
這種風格并不少見,我們可以將其映射到[b,e)這樣的一個序列:
注意,這種修改是無關(guān)緊要的:我并沒有修改容器或者某些由C++標準庫支持的將容器映射到模型進行遍歷的容器類的層次結(jié)構(gòu)。這是改寫的一種形式而不是重構(gòu)。
我選擇這個例子是為了說明這些泛型編程技術(shù)并不局限于流行的標準庫。它們也符合常見的“面向?qū)ο?rdquo;的定義,但是它們卻不是面向?qū)ο蟮摹?/p>
關(guān)于C++的代碼一定是面向?qū)ο螅ㄒ馕吨诿總€地方都會使用層次結(jié)構(gòu)和虛函數(shù))的觀點深深地影響了人們對C++性能的評價。還有一些人認為當需要解決多種類型的運行的問題只有面向?qū)ο蟛攀亲詈玫摹T谝郧埃乙彩沁@么想的。但是事實上,它也有死板的一面(比如并不是所有相關(guān)類型都屬于同一層次結(jié)構(gòu))并且虛函數(shù)無法作為內(nèi)聯(lián)函數(shù)(這就使得處理許多簡單而重要的任務(wù)時會多花費大量的時間)。
下一篇將會圍繞“對于可靠的軟件,垃圾回收機制必不可少。”的觀點進行說明……
本文翻譯自,作者為:C++之父Bjarne Stroustrup
本文譯者為慧都控件網(wǎng)——回憶和感動,轉(zhuǎn)載請注明:本文轉(zhuǎn)載自慧都控件網(wǎng)
【年終大促 巔峰盛“慧”】促銷火熱進行中iPhone 6 Plus、iPhone 6、iPad Air等你拿 <<<<點擊查看
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn