| 導購 | 订阅 | 在线投稿
分享
 
 
當前位置: 王朝網路 >> c/c++ >> 初學者,你應當如何學習C++以及編程
 

初學者,你應當如何學習C++以及編程

2008-06-01 02:10:02  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
 
  javascript是世界上最受誤解的語言,其實C++何嘗不是。坊間流傳的錯誤的C++學習方法一抓就是一大把。我自己在學習C++的過程中也走了許多彎路,浪費了不少時間。

  爲什麽會存在這麽多錯誤熟悉?原因主要有三個,一是C++語言的細節太多。二是一些聞名的C++書籍總在(不管有意還是無意)暗示語言細節的重要性和有趣。三是現代C++庫的開發哲學必須用到一些犄角旮旯的語言細節(但注重,是庫設計,不是日常編程)。這些共同塑造了C++社群的整體心態和哲學。

  單是第一條還未必能夠成氣候,其它語言的細節也不少(盡管比起C++起來還是小巫見大巫),就拿Javascript來說,作用域規則,名字查找,closure,for/in,這些都是細節,而且其中還有違反直覺的。但許多動態語言的程序員的理念我猜大約是學到哪用到哪罷。但C++就不一樣了,學C++之人有一種類似于被暗示的潛在心態,就是一定要先把語言核心基本上吃透了才能下手寫出漂亮的程序。這首先就錯了。這個意識形成的原因在第二點,C++書籍。市面上的C++書籍不計其數,但有一個共同的缺點,就是講語言細節的書太多——《C++ gotchas》,《Effective C++》,《More Effective C++》,但無可厚非的是,C++是這樣一門語言:要拿它滿足現代編程理念的需求,尤其是C++庫開發的需求,還必須得關注語言細節,乃至于在C++中利用語言細節已經成了一門學問。比如C++模板在設計之初根本沒有想到模板元編程這回事,更沒想到C++模板系統是圖靈完備的,這也就導致了《Modern C++ Design》和《C++ Template Metaprogramming》的驚世駭俗。

  這些技術的出現爲什麽驚世駭俗,打個比方,就好比是一塊大家都認爲已經熟悉無比,再無秘密可言的土地上,忽然某天有人挖到原來地下還蘊藏著最豐富的石油。在這之前的C++雖然也有一些細節,但也還算輕易把握,那可是C++程序員們的happy old times,因爲C++的一切都一覽無余,everything is figured out。然而《Modern C++ Design》的出世告訴人們,「瞧,還有多少細節你們沒有把握啊。」于是C++程序員們久違的激情被重燃起來,奮不顧身的踏入細節的沼澤中。尤其是,模板編程將C++的細節進一步挖掘到了極致——我們幹嘛關心涉及類對象的隱式轉換的優先級高低?看看boost::is_base_of就可以知道有多詭異了。

  但最大的問題還在于,對于這些細節的關注還真有它合適的理由:我們要開發現代模板庫,要開發active library,就必須動用模板編程技術,要動用模板編程技術,就必須利用語言的犄角旮旯,enable_if,type_traits,甚至連早就古井無波的C宏也在亂世中重生,看看boost::preprocessor有多詭異就知道了,連C宏的圖靈完備性(預編譯期的)都被挖掘出來了。爲什麽要做這些?好玩?標榜?都不是,開發庫的實際需求。但這也正是最大的悲哀了。在boost裏面因實際需求而動用語言細節最終居然能神奇的完成任務的最好教材就是boost::foreach,這個小設施對語言細節的發掘達到了驚天地泣鬼神的地步,不信你先試著自己去看看它的源代碼,再看看作者介紹它的文章吧。而boost::typeof也不甘其後——C++語言裏面有太多被「發現」而不是被「發明」的技術。難道最初無意設置這些語言規則的家夥們都是Oracles?

  因爲沒有variadic templates,人們用宏加上缺省模板參數來實現類似效果。因爲沒有concepts,人們用模板加上析構函數的細節來完成類似工作。因爲沒有typeof,人們用模板元編程和宏加上無盡的細節來實現目標… C++開發者們的DIY精神不可謂不強。

  然而,假如僅僅是因爲要開發優秀的庫,那麽涉及這些細節都還是情有可原的,至少在C++09出現並且編譯器廠商跟上之前,這些都還能說是不得已而爲之。但我們廣大的C++程序員呢?大衆是輕易被誤導的,我也曾經是。以爲把握了更多的語言細節就更牛,但實際卻是那些語言細節十有八九是平時編程用都用不到的。C++中衆多的細節雖然在庫設計者手裏面有其用武之地,但普通程序員則根本無需過多關注,尤其是沒有實際動機的關注。一般性的編碼實踐准則,以及基本的編程能力和基本功,乃至基本的程序設計理論以及算法設計。才是真正需要花時間把握的東西。

  學習最佳編碼實踐比學習C++更重要。看優秀的代碼也比埋頭用差勁的編碼方式寫垃圾代碼要有效。直接、清楚、明了、KISS地表達意圖比玩編碼花招要重要…

  避免去過問任何語言細節,除非必要。這個必要是指在實際編程當中碰到問題,這樣就算需要過問細節,也是最省事的,懶惰者原則嘛。一個把握了基本的編程理念並有較強學習能力的程序員在用一門生疏的語言編程時就算拿著那本語言的聖經從索引翻起也可以編出合格的程序來。十年學會編程不是指對每門語言都得十年,那一輩子才能學幾門語言哪,假如按字母順序學的話一輩子都別指望學到Ruby了;十年學習編程更不是指先把語言特性從粗到細全都吃透才敢下手編程,在實踐中提高才是最重要的。

  至于這種摳語言細節的哲學爲何能在社群裏面呈野火燎原之勢,就是一個心理學的問題了。想像人們在論壇上討論問題時,一個對語言把握很細致的人肯定能夠得到更多的佩服,而由于論壇上的問題大多是小問題,所以解決實際問題的真正能力並不能得到顯現,也就是說,知識型的人能夠得到更多佩服,後者便成爲動力和仿效的砝碼。然而真正的編程能力是與語言細節沒關系的,熟練運用一門語言能夠幫你最佳表達你的意圖,但熟練運用一門語言絕不意味著要把它的邊邊角角全都記住。懂得一些常識,有了編程的基本直覺,碰到一些細節錯誤的時候再去查書,是最節省時間的辦法。

  C++的書,Bjarne的聖經《The C++ Programming Language》是高屋建瓴的。《大規模C++程序設計》是挺務實的。《Accelerated C++》是最佳入門的。《C++ Templates》是僅作參考的。《C++ Template Metaprogramming》是精力過剩者可以玩一玩的,普通程序員碰都別碰的。《ISO.IEC C++ Standard 14882》不是拿來讀的。Bjarne最近在做C++的教育,新書是絕對可以期待的。

  

   P.S. 關于如何學習編程,g9的blog上有許多出色的文章:這裏,這裏,這裏,這裏… 實際上,我建議你去把g9老大的blog翻個底朝天 :P

  再P.S. 書單?我是遑于給出一個類似《C++初學者必讀》這種書單的。C++的書不計其數,被公認的好書也不勝枚舉。只不過有些書輕易給初學者造成一種錯覺,就是「學習C++就應該是這個樣子的」。比如有朋友提到的《高質量C/C++編程》,這本書有價值,但不適合初學者,初學者讀這樣的書輕易一葉障目不見泰山。實際上,正確的態度是,細節是必要的。但細節是次要的。其實學習編程我覺得應該最先學習如何用僞碼表達思想呢,君不見《IntrodUCtion to Algorithm》裏面的代碼?《TAOCP》中的代碼?哦,對了它們是自己建立的語言,但這種僅教學目的的語言的目的就是爲了避免讓寫程序的人一開始就忘了寫程序是爲了完成功能,以爲寫程序就是和語言細節作鬥爭了。Bjarne說程序的正確性最重要,boost的編碼標准裏面也將正確性列在性能前面。

  此外,一旦建立了正確的學習編程的理念,其實什麽書(只要不是太垃圾的)都有些用處。都當成參考書,用的時候從目錄或索引翻,基本就對了。

  再再P.S. myan老大和g9老大都給出了許多出色的見解。我不得不再加上一個P.S。具體我就不摘錄了,假如你讀到這裏,請務必往下看他們的評論。轉載者別忘了轉載他們的評論:-)

  許多朋友都問我同一個問題,到底要不要學習C++。其實這個問題問得很沒有意義。「學C++」和「不學C++」這個二分法是沒意義的,爲什麽?因爲這個問題很表面,甚至很浮躁。重要的不是你把握的語言,而是你把握的能力,借用myan老大的話,「重要的是這個磨練過程,而不是結果,要的是你粗壯的腿,而不是你身上背的那袋鹽巴。」。此外學習C++的意義其實真的是醉翁之意不在酒,像C/C++這種系統級語言,在學習的過程中必須要涉及到一些底層知識,如內存治理、編譯連接系統、彙編語言、硬件體系結構等等等等知識(注重,這不包括過分犄角旮旯的語言枝節)。這些東西也就是所謂的內功了(其實最最重要的內功還是長期學習所磨練出來的自學能力)。對此大嘴Joel在《Joel On Software》裏面提到的漏洞抽象定律闡述得就非常漂亮。

  所以,答案是,讓你成爲高手的並不是你把握什麽語言,精通C++未必就能讓你成爲高手,不精通C++也未必就能讓你成爲低手。我想大家都不會懷疑g9老大假如要抄起C++做一個項目的話會比大多數自認熟練C++的人要做得漂亮。所以要害的不是語言這個表層的東西,而是底下的本質矛盾。當然,不是說那就什麽語言都不要學了,按照一種曹操的邏輯,「天下語言,唯imperative與declarative耳」。C++是前者裏面最複雜的一種,支持最廣泛的編程範式。借用當初數學系入學大會上一個老師的話,「你數學都學了,還有什麽不能學的呢?」。學語言是一個途徑,假如你把它用來磨練自己,可以。假如你把它用來作爲學習系統底層知識的鑰匙,可以。假如你把它用來作爲學習如何編寫優秀的代碼,如何組織大型的程序,如何進行抽象設計,可以。假如掉書袋,光啃細節,我認爲不可以(除非你必須要用到細節,像boost庫的coder們)。

  然後再借用一下g9老大的《銀彈和我們的職業》中的話:

  銀彈和我們的職業發展有什麽相幹?很簡單:我們得把時間用于學習解決本質困難。新技術給高手帶來方便。菜鳥們卻不用指望被新技術拯救。沿用以前的比喻, 一流的攝影師不會因爲相機的更新換代而丟掉飯碗,反而可能借助先進技術留下傳世佳作。因爲攝影的本質困難,還是攝影師的藝術感覺。熱門技術也就等于相機。 不停追新,學習這個框架,那個軟件,好比成天鑽研不同相機的說明書。而熱門技術後的來龍去脈,才好比攝影技術。爲什麽推出這個框架?它解決了什麽其它框架 不能解決的問題?它在哪裏適用?它在哪裏不適用?它用了什麽新的設計?它改進了哪些舊的設計?Why is forever. 和 朋友聊天時提到Steve McConnell的《Professional Software Development》裏面引了一個調查,說軟件開發技術的半衰期20年。也就是說20年後我們現在知識裏一半的東西過時。相當不壞。朋友打趣道:「應 該說20年後IT界一半的技術過時,我們學的過時技術遠遠超過這個比例。具體到某人,很可能5年他就廢了」。話雖悲觀,但可見選擇學習內容的重要性。學習 本質技藝(技術遲早過時,技藝卻常用長新)還有一好處,就是不用看著自己心愛的技術受到挑戰的時候幹嚎。C/C++過時就過時了呗,只要有其它的系統編程 語言。Java倒了就倒了呗,未必我不能用.NET?Ruby昙花一現又如何。假如用得不爽,換到其它動態語言就是了。J2EE被廢了又怎樣?未必我們就 做不出分布系統了?這裏還舉了更多的例子。

  一句話,只有人是真正的銀彈。職業發展的目標,就是把自己變成銀彈。那時候,你就不再是人,而是人彈。

  最後就以我在Bjarne的衆多訪談當中摘錄的一些關于如何學習C++(以及編程)的看法結束吧(沒空逐段翻譯了,只將其中我覺得最重要的幾段譯了一下,當然,其它也很重要,這些段落是在Bjarne的所有采訪稿中摘抄出來的,所以強烈建議都過目一下):

  I suspect that people think too little about what they want to build, too little about what would make it correct, and too much about "efficiency" and following fashions of programming style. The key questions are always: "what do I want to do?" and "how do I know that I have done if?". Strategies for testing enters into my concerns from well before I write the firat line of code, and that despite my view that you have to write code very early - rather than wait until a design is complete.

  

   譯:我感覺人們過多關注了所謂「效率」以及跟隨編程風格的潮流,卻嚴重忽視了本不該被忽視的問題,如「我究竟想要構建什麽樣的系統」、「怎樣才能使它正確」。最要害的問題永遠是:「我究竟想要做什麽?」和「如何才能知道我的系統是否已經完成了呢?」就拿我來說吧,我會在編寫第一行代碼之前就考慮測試方案,而且這還是在我關于應當早于設計完成之前就進行編碼的觀點的前提之下。

  Obviously, C++ is very complex. Obviously, people get lost. However, most peple get lost when they get diverted into becoming language lawyers rather than getting lost when they have a clear idea of what they want to eXPress and simply look at C++ language features to see how to express it. Once you know data absreaction, class hierarchies (object-oriented programming), and parameterization with types (generic programming) in a fairly general way, the C++ language features fall in place.

  譯:誠然,C++非常複雜。誠然,人們迷失其中了。然而問題是,大多數人不是因爲首先對自己想要表達什麽有了清楚的熟悉只不過在去C++語言中搜尋合適的語言特性時迷失的,相反,大多數人是在不覺成爲語言律師的路上迷失在細節的叢林中的。事實是,只需對數據抽象、類體系結構(OOP)以及參數化類型(GP)有一個相當一般層面的了解,C++紛繁的語言特性也就清楚起來了。

  Well, I don't think I made such a trade-off. I want elegant and efficient code. Sometimes I get it. These dichotomies (between efficiency versus correctness, efficiency versus programmer time, efficiency versus high-level, et cetera.) are bogus.

  I think the real problem is that "we" (that is, we software developers) are in a permanent state of emergency, grASPing at straws to get our work done. We perform many minor miracles through trial and error, excessive use of brute force, and lots and lots of testing, but--so often--it's not enough.

  Software developers have become adept at the difficult art of building reasonably reliable systems out of unreliable parts. The snag is that often we do not know exactly how we did it: a system just "sort of evolved" into something minimally acceptable. Personally, I prefer to know when a system will work, and why it will.

  There are more useful systems developed in languages deemed awful than in languages praised for being beautiful--many more. The purpose of a programming language is to help build good systems, where "good" can be defined in many ways. My brief definition is, correct, maintainable, and adequately fast. Aesthetics matter, but first and foremost a language must be useful; it must allow real-world programmers to express real-world ideas succinctly and affordably.

  I'm sure that for every programmer that dislikes C++, there is one who likes it. However, a friend of mine went to a conference where the keynote speaker asked the audience to indicate by show of hands, one, how many people disliked C++, and two, how many people had written a C++ program. There were twice as many people in the first group than the second. Expressing dislike of something you don't know is usually known as prejudice. Also, complainers are always louder and more certain than proponents--reasonable people acknowledge flaws. I think I know more about the problems with C++ than just about anyone, but I also know how to avoid them and how to use C++'s strengths.

  

   In any case, I don't think it is true that the programming languages are so difficult to learn. For example, every first-year university biology textbook contains more details and deeper theory than even an expert-level programming-language book. Most applications involve standards, operating systems, libraries, and tools that far exceed modern programming languages in complexity. What is difficult is the appreciation of the underlying techniques and their application to real-world problems. Obviously, most current languages have many parts that are unnecessarily complex, but the degree of those complexities compared to some ideal minimum is often exaggerated.

  We need relatively complex language to deal with absolutely complex problems. I note that English is arguably the largest and most complex language in the world (measured in number of Words and idioms), but also one of the most successful.

  C++ provides a nice, extended case study in the evolutionary approach. C compatibility has been far harder to maintain than I or anyone else expected. Part of the reason is that C has kept evolving, partially guided by people who insist that C++ compatibility is neither necessary nor good for C. Another reason-- probably even more important--is that organizations prefer interfaces that are in the C/C++ subset so that they can support both languages with a single effort. This leads to a constant pressure on users not to use the most powerful C++ features and to myths about why they should be used "carefully," "infrequently," or "by experts only." That, combined with backwards-looking teaching of C++, has led to many failures to reap the potential benefits of C++ as a high-level language with powerful abstraction mechanisms.

  The question is how deeply integrated into the application those system dependencies are. I prefer the application to be designed conceptually in isolation from the underlying system, with an explicitly defined interface to "the outer world," and then integrated through a thin layer of interface code.

  Had I had a chance to name the style of programming I like best, it would have been "class-oriented programming", but then I'm not particularly good at finding snappy names. The school of thought that I belong to - rooted in Simula and related design philosophies - emphasizes the role of compile-time checking and flexible (static) type systems. Reasoning about the behavior of a program has to be rooted in the (static) structure of the source code. The focus should be on guarantees, invariant, etc. which are closely tied to that static structure. This is the only way I know to effectively deal with correctness. Testing is essential but cannot be systematic and complete without a good internal program structure - simple-minded blackbox testing of any significant system is infeasible because of the exponential explosion of states.

  

   So, I recommend people to think in terms of class invariants, exception handling guarantees, highly structured resource management, etc. I should add that I intensely dislike debugging (as ah hoc and unsystematic) and strongly prefer reasoning about source code and systematic testing.

  Pros: flexibility, generality, performance, portability, good tool support, available on more platforms than any competitor except C, Access to hardware and system resources, good availability of programmers and designers. Cons: complexity, sub-optimal use caused by poor teaching and myths.
 
 
 
上一篇《神話與謬誤:爭論C++前你應當知道什麽》
下一篇《C++引用計數的智能指針有效回收方法》
 
 
 
 
 
 
日版寵物情人插曲《Winding Road》歌詞

日版寵物情人2017的插曲,很帶節奏感,日語的,女生唱的。 最後聽見是在第8集的時候女主手割傷了,然後男主用嘴幫她吸了一下,插曲就出來了。 歌手:Def...

兄弟共妻,我成了他們夜裏的美食

老鍾家的兩個兒子很特別,就是跟其他的人不太一樣,魔一般的執著。兄弟倆都到了要結婚的年齡了,不管自家老爹怎麽磨破嘴皮子,兄弟倆說不娶就不娶,老父母爲兄弟兩操碎了心...

如何磨出破洞牛仔褲?牛仔褲怎麽剪破洞?

把牛仔褲磨出有線的破洞 1、具體工具就是磨腳石,下面墊一個硬物,然後用磨腳石一直磨一直磨,到把那塊磨薄了,用手撕開就好了。出來的洞啊很自然的。需要貓須的話調幾...

我就是掃描下圖得到了敬業福和愛國福

先來看下敬業福和愛國福 今年春節,支付寶再次推出了“五福紅包”活動,表示要“把欠大家的敬業福都還給大家”。 今天該活動正式啓動,和去年一樣,需要收集“五福”...

冰箱異味産生的原因和臭味去除的方法

有時候我們打開冰箱就會聞到一股異味,冰箱裏的這種異味是因爲一些物質發出的氣味的混合體,聞起來讓人惡心。 産生這些異味的主要原因有以下幾點。 1、很多人有這種習...

《極品家丁》1-31集大結局分集劇情介紹

簡介 《極品家丁》講述了現代白領林晚榮無意回到古代金陵,並追隨蕭二小姐化名“林三”進入蕭府,不料卻陰差陽錯上演了一出低級家丁拼搏上位的“林三升職記”。...

李溪芮《極品家丁》片尾曲《你就是我最愛的寶寶》歌詞

你就是我最愛的寶寶 - 李溪芮 (電視劇《極品家丁》片尾曲) 作詞:常馨內 作曲:常馨內 你的眉 又鬼馬的挑 你的嘴 又壞壞的笑 上一秒吵鬧 下...

烏梅的功效與作用以及烏梅的食用禁忌有哪些?

烏梅,又稱春梅,中醫認爲,烏梅味酸,性溫,無毒,具有安心、除熱、下氣、祛痰、止渴調中、殺蟲的功效,治肢體痛、肺痨病。烏梅泡水喝能治傷寒煩熱、止吐瀉,與幹姜一起制...

什麽是脂肪粒?如何消除臉部脂肪粒?

什麽是脂肪粒 在我們的臉上總會長一個個像脂肪的小顆粒,弄也弄不掉,而且顔色還是白白的。它既不是粉刺也不是其他的任何痘痘,它就是脂肪粒。 脂肪粒雖然也是由油脂...

網絡安全治理:國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰受害者

來源:中國青年報 新的攻擊方法不斷湧現,黑客幾乎永遠占據網絡攻擊的上風,我們不可能通過技術手段杜絕網絡攻擊。國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰...

河南夫妻在溫嶺網絡直播“造人”內容涉黃被刑事拘留

夫妻網絡直播“造人”爆紅   1月9日,溫嶺城北派出所接到南京警方的協查通告,他們近期打掉了一個涉黃直播APP平台。而根據掌握的線索,其中有一對涉案的夫妻主播...

如何防止牆紙老化?牆紙變舊變黃怎麽辦?

如何防止牆紙老化? (1)選擇透氣性好的牆紙 市場上牆紙的材質分無紡布的、木纖維的、PVC的、玻璃纖維基材的、布面的等,相對而言,PVC材質的牆紙最不透氣...

鮮肌之謎非日本生産VS鮮肌之謎假日貨是謠言

觀點一:破日本銷售量的“鮮肌之謎” 非日本生産 近一段時間,淘寶上架了一款名爲“鮮肌之謎的” 鲑魚卵巢美容液,號稱是最近日本的一款推出的全新護膚品,産品本身所...

中國最美古詩詞精選摘抄

系腰裙(北宋詞人 張先) 惜霜蟾照夜雲天,朦胧影、畫勾闌。人情縱似長情月,算一年年。又能得、幾番圓。 欲寄西江題葉字,流不到、五亭前。東池始有荷新綠,尚小如...

關于女人的經典語句

關于女人的經典語句1、【做一個獨立的女人】 思想獨立:有主見、有自己的人生觀、價值觀。有上進心,永遠不放棄自己的理想,做一份自己喜愛的事業,擁有快樂和成就...

未來我們可以和性愛機器人結婚嗎?

你想體驗機器人性愛嗎?你想和性愛機器人結婚嗎?如果你想,機器人有拒絕你的權利嗎? 近日,第二屆“國際人類-機器人性愛研討會”大會在倫敦金史密斯大學落下帷幕。而...

全球最變態的十個地方

10.土耳其地下洞穴城市 變態指數:★★☆☆☆ 這是土耳其卡帕多西亞的一個著名景點,傳說是當年基督教徒們爲了躲避戰爭而在此修建。裏面曾住著20000人,...

科學家稱,人類死亡後意識將在另外一個宇宙中繼續存活

據英國《每日快報》報道,一位科學家兼理論家Robert Lanza博士宣稱,世界上並不存在人類死亡,死亡的只是身體。他認爲我們的意識借助我們體內的能量生存,而且...

《屏裏狐》片頭曲《我愛狐狸精》歌詞是什麽?

《我愛狐狸精》 - 劉馨棋   (電視劇《屏裏狐》主題曲)   作詞:金十三&李旦   作曲:劉嘉   狐狸精 狐狸仙   千年修...

 
 
 
  javascript是世界上最受誤解的語言,其實C++何嘗不是。坊間流傳的錯誤的C++學習方法一抓就是一大把。我自己在學習C++的過程中也走了許多彎路,浪費了不少時間。   爲什麽會存在這麽多錯誤熟悉?原因主要有三個,一是C++語言的細節太多。二是一些聞名的C++書籍總在(不管有意還是無意)暗示語言細節的重要性和有趣。三是現代C++庫的開發哲學必須用到一些犄角旮旯的語言細節(但注重,是庫設計,不是日常編程)。這些共同塑造了C++社群的整體心態和哲學。   單是第一條還未必能夠成氣候,其它語言的細節也不少(盡管比起C++起來還是小巫見大巫),就拿Javascript來說,作用域規則,名字查找,closure,for/in,這些都是細節,而且其中還有違反直覺的。但許多動態語言的程序員的理念我猜大約是學到哪用到哪罷。但C++就不一樣了,學C++之人有一種類似于被暗示的潛在心態,就是一定要先把語言核心基本上吃透了才能下手寫出漂亮的程序。這首先就錯了。這個意識形成的原因在第二點,C++書籍。市面上的C++書籍不計其數,但有一個共同的缺點,就是講語言細節的書太多——《C++ gotchas》,《Effective C++》,《More Effective C++》,但無可厚非的是,C++是這樣一門語言:要拿它滿足現代編程理念的需求,尤其是C++庫開發的需求,還必須得關注語言細節,乃至于在C++中利用語言細節已經成了一門學問。比如C++模板在設計之初根本沒有想到模板元編程這回事,更沒想到C++模板系統是圖靈完備的,這也就導致了《Modern C++ Design》和《C++ Template Metaprogramming》的驚世駭俗。   這些技術的出現爲什麽驚世駭俗,打個比方,就好比是一塊大家都認爲已經熟悉無比,再無秘密可言的土地上,忽然某天有人挖到原來地下還蘊藏著最豐富的石油。在這之前的C++雖然也有一些細節,但也還算輕易把握,那可是C++程序員們的happy old times,因爲C++的一切都一覽無余,everything is figured out。然而《Modern C++ Design》的出世告訴人們,「瞧,還有多少細節你們沒有把握啊。」于是C++程序員們久違的激情被重燃起來,奮不顧身的踏入細節的沼澤中。尤其是,模板編程將C++的細節進一步挖掘到了極致——我們幹嘛關心涉及類對象的隱式轉換的優先級高低?看看boost::is_base_of就可以知道有多詭異了。   但最大的問題還在于,對于這些細節的關注還真有它合適的理由:我們要開發現代模板庫,要開發active library,就必須動用模板編程技術,要動用模板編程技術,就必須利用語言的犄角旮旯,enable_if,type_traits,甚至連早就古井無波的C宏也在亂世中重生,看看boost::preprocessor有多詭異就知道了,連C宏的圖靈完備性(預編譯期的)都被挖掘出來了。爲什麽要做這些?好玩?標榜?都不是,開發庫的實際需求。但這也正是最大的悲哀了。在boost裏面因實際需求而動用語言細節最終居然能神奇的完成任務的最好教材就是boost::foreach,這個小設施對語言細節的發掘達到了驚天地泣鬼神的地步,不信你先試著自己去看看它的源代碼,再看看作者介紹它的文章吧。而boost::typeof也不甘其後——C++語言裏面有太多被「發現」而不是被「發明」的技術。難道最初無意設置這些語言規則的家夥們都是Oracles?   因爲沒有variadic templates,人們用宏加上缺省模板參數來實現類似效果。因爲沒有concepts,人們用模板加上析構函數的細節來完成類似工作。因爲沒有typeof,人們用模板元編程和宏加上無盡的細節來實現目標… C++開發者們的DIY精神不可謂不強。   然而,假如僅僅是因爲要開發優秀的庫,那麽涉及這些細節都還是情有可原的,至少在C++09出現並且編譯器廠商跟上之前,這些都還能說是不得已而爲之。但我們廣大的C++程序員呢?大衆是輕易被誤導的,我也曾經是。以爲把握了更多的語言細節就更牛,但實際卻是那些語言細節十有八九是平時編程用都用不到的。C++中衆多的細節雖然在庫設計者手裏面有其用武之地,但普通程序員則根本無需過多關注,尤其是沒有實際動機的關注。一般性的編碼實踐准則,以及基本的編程能力和基本功,乃至基本的程序設計理論以及算法設計。才是真正需要花時間把握的東西。   學習最佳編碼實踐比學習C++更重要。看優秀的代碼也比埋頭用差勁的編碼方式寫垃圾代碼要有效。直接、清楚、明了、KISS地表達意圖比玩編碼花招要重要…   避免去過問任何語言細節,除非必要。這個必要是指在實際編程當中碰到問題,這樣就算需要過問細節,也是最省事的,懶惰者原則嘛。一個把握了基本的編程理念並有較強學習能力的程序員在用一門生疏的語言編程時就算拿著那本語言的聖經從索引翻起也可以編出合格的程序來。十年學會編程不是指對每門語言都得十年,那一輩子才能學幾門語言哪,假如按字母順序學的話一輩子都別指望學到Ruby了;十年學習編程更不是指先把語言特性從粗到細全都吃透才敢下手編程,在實踐中提高才是最重要的。   至于這種摳語言細節的哲學爲何能在社群裏面呈野火燎原之勢,就是一個心理學的問題了。想像人們在論壇上討論問題時,一個對語言把握很細致的人肯定能夠得到更多的佩服,而由于論壇上的問題大多是小問題,所以解決實際問題的真正能力並不能得到顯現,也就是說,知識型的人能夠得到更多佩服,後者便成爲動力和仿效的砝碼。然而真正的編程能力是與語言細節沒關系的,熟練運用一門語言能夠幫你最佳表達你的意圖,但熟練運用一門語言絕不意味著要把它的邊邊角角全都記住。懂得一些常識,有了編程的基本直覺,碰到一些細節錯誤的時候再去查書,是最節省時間的辦法。   C++的書,Bjarne的聖經《The C++ Programming Language》是高屋建瓴的。《大規模C++程序設計》是挺務實的。《Accelerated C++》是最佳入門的。《C++ Templates》是僅作參考的。《C++ Template Metaprogramming》是精力過剩者可以玩一玩的,普通程序員碰都別碰的。《ISO.IEC C++ Standard 14882》不是拿來讀的。Bjarne最近在做C++的教育,新書是絕對可以期待的。   P.S. 關于如何學習編程,g9的blog上有許多出色的文章:這裏,這裏,這裏,這裏… 實際上,我建議你去把g9老大的blog翻個底朝天 :P   再P.S. 書單?我是遑于給出一個類似《C++初學者必讀》這種書單的。C++的書不計其數,被公認的好書也不勝枚舉。只不過有些書輕易給初學者造成一種錯覺,就是「學習C++就應該是這個樣子的」。比如有朋友提到的《高質量C/C++編程》,這本書有價值,但不適合初學者,初學者讀這樣的書輕易一葉障目不見泰山。實際上,正確的態度是,細節是必要的。但細節是次要的。其實學習編程我覺得應該最先學習如何用僞碼表達思想呢,君不見《IntrodUCtion to Algorithm》裏面的代碼?《TAOCP》中的代碼?哦,對了它們是自己建立的語言,但這種僅教學目的的語言的目的就是爲了避免讓寫程序的人一開始就忘了寫程序是爲了完成功能,以爲寫程序就是和語言細節作鬥爭了。Bjarne說程序的正確性最重要,boost的編碼標准裏面也將正確性列在性能前面。   此外,一旦建立了正確的學習編程的理念,其實什麽書(只要不是太垃圾的)都有些用處。都當成參考書,用的時候從目錄或索引翻,基本就對了。   再再P.S. myan老大和g9老大都給出了許多出色的見解。我不得不再加上一個P.S。具體我就不摘錄了,假如你讀到這裏,請務必往下看他們的評論。轉載者別忘了轉載他們的評論:-)   許多朋友都問我同一個問題,到底要不要學習C++。其實這個問題問得很沒有意義。「學C++」和「不學C++」這個二分法是沒意義的,爲什麽?因爲這個問題很表面,甚至很浮躁。重要的不是你把握的語言,而是你把握的能力,借用myan老大的話,「重要的是這個磨練過程,而不是結果,要的是你粗壯的腿,而不是你身上背的那袋鹽巴。」。此外學習C++的意義其實真的是醉翁之意不在酒,像C/C++這種系統級語言,在學習的過程中必須要涉及到一些底層知識,如內存治理、編譯連接系統、彙編語言、硬件體系結構等等等等知識(注重,這不包括過分犄角旮旯的語言枝節)。這些東西也就是所謂的內功了(其實最最重要的內功還是長期學習所磨練出來的自學能力)。對此大嘴Joel在《Joel On Software》裏面提到的漏洞抽象定律闡述得就非常漂亮。   所以,答案是,讓你成爲高手的並不是你把握什麽語言,精通C++未必就能讓你成爲高手,不精通C++也未必就能讓你成爲低手。我想大家都不會懷疑g9老大假如要抄起C++做一個項目的話會比大多數自認熟練C++的人要做得漂亮。所以要害的不是語言這個表層的東西,而是底下的本質矛盾。當然,不是說那就什麽語言都不要學了,按照一種曹操的邏輯,「天下語言,唯imperative與declarative耳」。C++是前者裏面最複雜的一種,支持最廣泛的編程範式。借用當初數學系入學大會上一個老師的話,「你數學都學了,還有什麽不能學的呢?」。學語言是一個途徑,假如你把它用來磨練自己,可以。假如你把它用來作爲學習系統底層知識的鑰匙,可以。假如你把它用來作爲學習如何編寫優秀的代碼,如何組織大型的程序,如何進行抽象設計,可以。假如掉書袋,光啃細節,我認爲不可以(除非你必須要用到細節,像boost庫的coder們)。   然後再借用一下g9老大的《銀彈和我們的職業》中的話:   銀彈和我們的職業發展有什麽相幹?很簡單:我們得把時間用于學習解決本質困難。新技術給高手帶來方便。菜鳥們卻不用指望被新技術拯救。沿用以前的比喻, 一流的攝影師不會因爲相機的更新換代而丟掉飯碗,反而可能借助先進技術留下傳世佳作。因爲攝影的本質困難,還是攝影師的藝術感覺。熱門技術也就等于相機。 不停追新,學習這個框架,那個軟件,好比成天鑽研不同相機的說明書。而熱門技術後的來龍去脈,才好比攝影技術。爲什麽推出這個框架?它解決了什麽其它框架 不能解決的問題?它在哪裏適用?它在哪裏不適用?它用了什麽新的設計?它改進了哪些舊的設計?Why is forever. 和 朋友聊天時提到Steve McConnell的《Professional Software Development》裏面引了一個調查,說軟件開發技術的半衰期20年。也就是說20年後我們現在知識裏一半的東西過時。相當不壞。朋友打趣道:「應 該說20年後IT界一半的技術過時,我們學的過時技術遠遠超過這個比例。具體到某人,很可能5年他就廢了」。話雖悲觀,但可見選擇學習內容的重要性。學習 本質技藝(技術遲早過時,技藝卻常用長新)還有一好處,就是不用看著自己心愛的技術受到挑戰的時候幹嚎。C/C++過時就過時了呗,只要有其它的系統編程 語言。Java倒了就倒了呗,未必我不能用.NET?Ruby昙花一現又如何。假如用得不爽,換到其它動態語言就是了。J2EE被廢了又怎樣?未必我們就 做不出分布系統了?這裏還舉了更多的例子。   一句話,只有人是真正的銀彈。職業發展的目標,就是把自己變成銀彈。那時候,你就不再是人,而是人彈。   最後就以我在Bjarne的衆多訪談當中摘錄的一些關于如何學習C++(以及編程)的看法結束吧(沒空逐段翻譯了,只將其中我覺得最重要的幾段譯了一下,當然,其它也很重要,這些段落是在Bjarne的所有采訪稿中摘抄出來的,所以強烈建議都過目一下):   I suspect that people think too little about what they want to build, too little about what would make it correct, and too much about "efficiency" and following fashions of programming style. The key questions are always: "what do I want to do?" and "how do I know that I have done if?". Strategies for testing enters into my concerns from well before I write the firat line of code, and that despite my view that you have to write code very early - rather than wait until a design is complete.   譯:我感覺人們過多關注了所謂「效率」以及跟隨編程風格的潮流,卻嚴重忽視了本不該被忽視的問題,如「我究竟想要構建什麽樣的系統」、「怎樣才能使它正確」。最要害的問題永遠是:「我究竟想要做什麽?」和「如何才能知道我的系統是否已經完成了呢?」就拿我來說吧,我會在編寫第一行代碼之前就考慮測試方案,而且這還是在我關于應當早于設計完成之前就進行編碼的觀點的前提之下。   Obviously, C++ is very complex. Obviously, people get lost. However, most peple get lost when they get diverted into becoming language lawyers rather than getting lost when they have a clear idea of what they want to eXPress and simply look at C++ language features to see how to express it. Once you know data absreaction, class hierarchies (object-oriented programming), and parameterization with types (generic programming) in a fairly general way, the C++ language features fall in place.   譯:誠然,C++非常複雜。誠然,人們迷失其中了。然而問題是,大多數人不是因爲首先對自己想要表達什麽有了清楚的熟悉只不過在去C++語言中搜尋合適的語言特性時迷失的,相反,大多數人是在不覺成爲語言律師的路上迷失在細節的叢林中的。事實是,只需對數據抽象、類體系結構(OOP)以及參數化類型(GP)有一個相當一般層面的了解,C++紛繁的語言特性也就清楚起來了。   Well, I don't think I made such a trade-off. I want elegant and efficient code. Sometimes I get it. These dichotomies (between efficiency versus correctness, efficiency versus programmer time, efficiency versus high-level, et cetera.) are bogus.   I think the real problem is that "we" (that is, we software developers) are in a permanent state of emergency, grASPing at straws to get our work done. We perform many minor miracles through trial and error, excessive use of brute force, and lots and lots of testing, but--so often--it's not enough.   Software developers have become adept at the difficult art of building reasonably reliable systems out of unreliable parts. The snag is that often we do not know exactly how we did it: a system just "sort of evolved" into something minimally acceptable. Personally, I prefer to know when a system will work, and why it will.   There are more useful systems developed in languages deemed awful than in languages praised for being beautiful--many more. The purpose of a programming language is to help build good systems, where "good" can be defined in many ways. My brief definition is, correct, maintainable, and adequately fast. Aesthetics matter, but first and foremost a language must be useful; it must allow real-world programmers to express real-world ideas succinctly and affordably.   I'm sure that for every programmer that dislikes C++, there is one who likes it. However, a friend of mine went to a conference where the keynote speaker asked the audience to indicate by show of hands, one, how many people disliked C++, and two, how many people had written a C++ program. There were twice as many people in the first group than the second. Expressing dislike of something you don't know is usually known as prejudice. Also, complainers are always louder and more certain than proponents--reasonable people acknowledge flaws. I think I know more about the problems with C++ than just about anyone, but I also know how to avoid them and how to use C++'s strengths.   In any case, I don't think it is true that the programming languages are so difficult to learn. For example, every first-year university biology textbook contains more details and deeper theory than even an expert-level programming-language book. Most applications involve standards, operating systems, libraries, and tools that far exceed modern programming languages in complexity. What is difficult is the appreciation of the underlying techniques and their application to real-world problems. Obviously, most current languages have many parts that are unnecessarily complex, but the degree of those complexities compared to some ideal minimum is often exaggerated.   We need relatively complex language to deal with absolutely complex problems. I note that English is arguably the largest and most complex language in the world (measured in number of Words and idioms), but also one of the most successful.   C++ provides a nice, extended case study in the evolutionary approach. C compatibility has been far harder to maintain than I or anyone else expected. Part of the reason is that C has kept evolving, partially guided by people who insist that C++ compatibility is neither necessary nor good for C. Another reason-- probably even more important--is that organizations prefer interfaces that are in the C/C++ subset so that they can support both languages with a single effort. This leads to a constant pressure on users not to use the most powerful C++ features and to myths about why they should be used "carefully," "infrequently," or "by experts only." That, combined with backwards-looking teaching of C++, has led to many failures to reap the potential benefits of C++ as a high-level language with powerful abstraction mechanisms.   The question is how deeply integrated into the application those system dependencies are. I prefer the application to be designed conceptually in isolation from the underlying system, with an explicitly defined interface to "the outer world," and then integrated through a thin layer of interface code.   Had I had a chance to name the style of programming I like best, it would have been "class-oriented programming", but then I'm not particularly good at finding snappy names. The school of thought that I belong to - rooted in Simula and related design philosophies - emphasizes the role of compile-time checking and flexible (static) type systems. Reasoning about the behavior of a program has to be rooted in the (static) structure of the source code. The focus should be on guarantees, invariant, etc. which are closely tied to that static structure. This is the only way I know to effectively deal with correctness. Testing is essential but cannot be systematic and complete without a good internal program structure - simple-minded blackbox testing of any significant system is infeasible because of the exponential explosion of states.   So, I recommend people to think in terms of class invariants, exception handling guarantees, highly structured resource management, etc. I should add that I intensely dislike debugging (as ah hoc and unsystematic) and strongly prefer reasoning about source code and systematic testing.   Pros: flexibility, generality, performance, portability, good tool support, available on more platforms than any competitor except C, Access to hardware and system resources, good availability of programmers and designers. Cons: complexity, sub-optimal use caused by poor teaching and myths.
󰈣󰈤
 
 
 
  免責聲明:本文僅代表作者個人觀點,與王朝網路無關。王朝網路登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
 
小龍女彤彤之情溢皇都
龔潔
智能手機形象美女
崔潔彤
回家的路上----
中國一站(哈爾濱)
清明植物園的花。
桃花堤印象之豎版
 
>>返回首頁<<
 
 熱帖排行
 
 
 
 
© 2005- 王朝網路 版權所有