C/C++之爭(zhēng)
目前吵的很兇。
都說(shuō)什么C++快不行了,可是游戲開發(fā)這種東西,還是非C++莫屬,圖形開發(fā)這塊C++還是強(qiáng)項(xiàng)。我發(fā)現(xiàn)C#,JAVA之類的之所以能在企業(yè)級(jí)應(yīng)用和快速開發(fā)方面占有優(yōu)勢(shì),完全是因?yàn)閯e人已經(jīng)幫你封裝好了一套好用的API函數(shù),而不是這些語(yǔ)言的語(yǔ)法機(jī)制本身提供了多少優(yōu)點(diǎn),而C++和C卻不這么做,因?yàn)镃/C++相信使用它的程序員完全有能力自己封裝,沒(méi)必要替他們封裝。
對(duì)于C++提供的繼承、模板等高級(jí)特性,應(yīng)該謹(jǐn)慎使用,盡量做到繼承的層次很少,各個(gè)類之間是組合關(guān)系,從而達(dá)成一種平板結(jié)構(gòu),以實(shí)現(xiàn)各個(gè)類之間最低的耦合度,降低維護(hù)和理解的成本。同時(shí)由于類隱藏了數(shù)據(jù),又將特定的數(shù)據(jù)和函數(shù)綁定在了一起,這樣就可以減少全局變量的使用,降低了由于大量使用全局變量所引發(fā)的風(fēng)險(xiǎn)。同時(shí)類的封裝降低了各個(gè)函數(shù)之間通信的成本,減少了函數(shù)參數(shù)的個(gè)數(shù),而通過(guò)多態(tài)這一特性可以更加有效地降低函數(shù)調(diào)用的參數(shù)個(gè)數(shù)。
C與C++通過(guò)良好的設(shè)計(jì)都可以架構(gòu)一個(gè)優(yōu)秀的框架,而C++通過(guò)面向?qū)ο筮@一特性(類、繼承、多態(tài)等)可以更加有效的實(shí)現(xiàn)封裝和信息隱藏,但架構(gòu)不應(yīng)該太復(fù)雜,繼承層次不要過(guò)多,類和類應(yīng)該盡量是一種平板組合關(guān)系。
我的觀點(diǎn)是少一點(diǎn)語(yǔ)言之爭(zhēng),多學(xué)一點(diǎn)實(shí)用的技術(shù),真正起決定作用的往往是對(duì)具體技術(shù)的掌握,比如Windows運(yùn)行機(jī)制,Windows網(wǎng)絡(luò)編程基礎(chǔ),API函數(shù),3D數(shù)學(xué)基礎(chǔ),3D圖形學(xué)基礎(chǔ),DirectX提供的具體接口和函數(shù),游戲制作技術(shù)的熟悉,以及數(shù)據(jù)結(jié)構(gòu)和算法等等,到最后用什么語(yǔ)言來(lái)實(shí)現(xiàn)其實(shí)是一個(gè)次要的問(wèn)題了。至于架構(gòu)好點(diǎn)差點(diǎn)倒不是最重要的,沒(méi)有這些基礎(chǔ)知識(shí)的積累,東西憋都憋不出來(lái),更不要談什么架構(gòu)了。
附一些網(wǎng)友的觀點(diǎn):
我對(duì) C 和 C++都很喜歡,但是更喜歡用 C,因?yàn)楸容^簡(jiǎn)單。C++也很好,只是許多特性都用不上,我喜歡用最簡(jiǎn)單的辦法去解決實(shí)際的問(wèn)題,并盡量保證其合理性。做設(shè)計(jì)應(yīng)當(dāng)以實(shí)際問(wèn)題為出發(fā)點(diǎn),作抽象是好的,但是任何事物都有適用范圍,沒(méi)有人能夠?qū)懗鐾耆ㄓ玫摹⑵者m的代碼,用 C++ 也做不到。這類似于以不變應(yīng)萬(wàn)變和隨機(jī)應(yīng)變之間的關(guān)系。C++程序員有時(shí)候太過(guò)執(zhí)著于抽象設(shè)計(jì),執(zhí)著于通用庫(kù)的設(shè)計(jì),執(zhí)著于可重用,執(zhí)著于面向?qū)ο螅灾劣谕嗽O(shè)計(jì)的根本是為了解決實(shí)際問(wèn)題,忘了除了面向?qū)ο蟮脑O(shè)計(jì)方法還有更多其他的設(shè)計(jì)方法,忘了設(shè)計(jì)的簡(jiǎn)潔,忘了設(shè)計(jì)是否容易被他人所理解,忘了除了重用,還有更多需要注意的地方。C++使人們?cè)谠O(shè)計(jì)時(shí),在面向?qū)ο蟆⒊橄蠛涂芍赜蒙媳成狭颂喟ぃ灾劣谠S多人沉溺其中,而沒(méi)有更多的精力去做更多的事情。
以不變應(yīng)萬(wàn)變是相對(duì)的,而隨機(jī)應(yīng)變則是絕對(duì)的。也就類似于靜止是相對(duì)的,而運(yùn)動(dòng)與變化是絕對(duì)的,這樣一個(gè)哲學(xué)道理。因此,從這個(gè)角度上將,修改或重寫代碼都是絕對(duì)會(huì)發(fā)生的。而我們盡力所要保證的重用性,其實(shí)都是相對(duì)的重用性。因此,有必要考慮,是否真的需要花費(fèi)大量的精力,去保證這種相對(duì)的可重性。
我之所以要這樣講,是因?yàn)榻鼛啄辏芍赜眯员粡?qiáng)調(diào)得太多太過(guò)。以至于人們忘了自己真的需要做什么。
相對(duì)于代碼的可重用性,我更加看重代碼的可維護(hù)性和可擴(kuò)展性。好的代碼都是開放的,可維護(hù),可擴(kuò)展的。盡量保持扁平的層次結(jié)構(gòu),盡量使用基本的數(shù)據(jù)類型,盡量減少自定義的數(shù)據(jù)類型,使整個(gè)系統(tǒng)的設(shè)計(jì)更加容易被人所理解。
真正好的設(shè)計(jì),都是開放的,簡(jiǎn)潔的,易于理解的。畢竟維護(hù)的最基本的條件,就是先要理解現(xiàn)有的代碼。
而所謂的可重用性和抽象,都給以上目標(biāo)的實(shí)現(xiàn),帶來(lái)了極大的障礙。因此需要根據(jù)實(shí)際需求,在各個(gè)方面取得平衡。否則,一切關(guān)于語(yǔ)言的爭(zhēng)論都是毫無(wú)意義的。
一個(gè)系統(tǒng),不管你設(shè)計(jì)得多么抽象,多么可重用,他總有適用的范圍。而為了達(dá)到重用和抽象,所使用的技巧不管多么高明,如果它很難被理解的話也是毫無(wú)意義的。因?yàn)檫@個(gè)系統(tǒng)總有一天會(huì)走出他的適用范圍,這個(gè)時(shí)候就需要修改和維護(hù)其代碼。如果這個(gè)系統(tǒng)很難維護(hù),那么,就算它當(dāng)初的設(shè)計(jì)很高明,但也走到了生命的盡頭,逃脫不了被重寫的命運(yùn)。
因此,從實(shí)際出發(fā),分清主次,做自己真正該做的事情才是關(guān)鍵。感覺(jué)可重用和面向?qū)ο蟊粡?qiáng)調(diào)得太過(guò),以至于人們迷失了方向。
學(xué)習(xí)期。 c,簡(jiǎn)單,干練。簡(jiǎn)單到?jīng)]什么好學(xué)的。有用的技能都是在實(shí)際運(yùn)用中獲得exp然后lvup的。可以這么說(shuō),初學(xué)者可以很快得掌握c,但是基本上卻什么都不能做。立竿不能見(jiàn)影。這是c的簡(jiǎn)單干練所決定的,是必然的。 c++,復(fù)雜,強(qiáng)大。c++的這些特點(diǎn)已經(jīng)無(wú)須論證。遍地開花的垃圾c++程序員用鐵一般的事實(shí)說(shuō)明了一切。針對(duì)于與c的比較,仍然來(lái)說(shuō)說(shuō)立竿見(jiàn)影的問(wèn)題。我的觀點(diǎn)是,雖然這一點(diǎn)c++做得比c好一些,但是仍然不能達(dá)到立竿見(jiàn)影的程度。結(jié)論,就這個(gè)階段來(lái)說(shuō),不分勝負(fù)。
開發(fā)期。在任何軟工項(xiàng)目都處于“硬件受限”的時(shí)代和環(huán)境下,c是毫無(wú)疑問(wèn)的王者。(當(dāng)然,如果你腦容量可堪負(fù)荷,請(qǐng)使用asm)但是在現(xiàn)在,情況分2種。第1種,我是一個(gè)獨(dú)裁者。當(dāng)我需要清楚地知道我的代碼做了什么的時(shí)候,c->asm仍然是最適合的合作者。這種人多半是戰(zhàn)斗在“硬件受限”的原始時(shí)代。Linus就處于這樣一種時(shí)代,所以他不得不用c。不要告訴我linux可以跑在多么牛B的機(jī)器上,內(nèi)存可以多么的大,這是p話,linux的 kernel必須不能用盡一切可以觸及的資源,因?yàn)樗皇且粋€(gè)承載其他東西的方舟,他必須委屈自己假裝是在一個(gè)超級(jí)受限的環(huán)境下工作,把美味的梨子讓出來(lái)給依賴著它的兄弟姐妹們。所以,kernel類的開發(fā)者毫無(wú)疑問(wèn)是戰(zhàn)斗在一個(gè)“硬件受限”的原始時(shí)代,c->asm是他們最好的合作者。 ps.游戲引擎也算半個(gè)“硬件受限”環(huán)境。雖然不需要承載如kernel般繁多的東西,但是引擎最終將被用來(lái)產(chǎn)生實(shí)作品,從設(shè)計(jì)者的角度出發(fā),也必須在一定規(guī)模——沒(méi)錯(cuò),就是規(guī)模——上考慮到由這個(gè)引擎所生產(chǎn)出來(lái)的東西將要產(chǎn)生的負(fù)荷——這毫無(wú)疑問(wèn)地成為了一個(gè)“受限”的環(huán)境。——但是盡管如此,c- >asm也不一定就是最優(yōu)解,在我的觀點(diǎn)來(lái)看,這是語(yǔ)言無(wú)關(guān)的——當(dāng)然,目前可以做出的選擇不多,就個(gè)人而言,我仍然選擇了c++。第2種,我是一個(gè)追求高產(chǎn)的商人。在性能要求不太嚴(yán)苛的情況下,c就是一個(gè)渣。太多的東西需要自己去做,這意味著將會(huì)帶來(lái)冗長(zhǎng)的開發(fā)周期,這會(huì)導(dǎo)致成本的急劇增長(zhǎng),包括各種可量化的(人力物力財(cái)力)和不可量化的(團(tuán)隊(duì)穩(wěn)固性團(tuán)隊(duì)士氣)成本。因此,在這種環(huán)境下,c就是一個(gè)渣。c++毫無(wú)疑問(wèn)比c做得好。但是,在這個(gè)領(lǐng)域里,c和目前的c++都已經(jīng)失去了輝煌的寶座,新生代的高級(jí)語(yǔ)言都擁有給他們致命一擊的實(shí)力。結(jié)論,從表面來(lái)看,仍然是不分勝負(fù)。但是c在這一階段具有穩(wěn)定、明確的應(yīng)用領(lǐng)域,算是小勝吧。
運(yùn)行期。仍然是分成2種情況,效率關(guān)鍵和效率不關(guān)鍵的。在避開其他環(huán)節(jié)的情況下,前者當(dāng)然比后者更受歡迎。但是,運(yùn)行期的效率直接與開發(fā)期的質(zhì)量相關(guān),因此運(yùn)行期的事又是不可能和開發(fā)期完全隔開的。 “不管用什么樣的語(yǔ)言,都可以寫出糟糕的程序。”——這話也可以反過(guò)來(lái)說(shuō),“用任何一種語(yǔ)言,都可以寫出優(yōu)秀的程序。” 因此,在我眼中,這仍然是一個(gè)語(yǔ)言無(wú)關(guān)的問(wèn)題。不要把失敗的理由放在你無(wú)法控制的地方,優(yōu)秀的進(jìn)化者會(huì)改變自己適應(yīng)環(huán)境。——這是我的觀點(diǎn),因此,我更希望自己能成為“用任何一種語(yǔ)言,都可以寫出優(yōu)秀的程序”這樣一個(gè)開發(fā)者。我認(rèn)為,每一個(gè)以成為優(yōu)秀開發(fā)者為目標(biāo)的程序員,都應(yīng)該以這樣一種精神為指導(dǎo),雖然不一定要確實(shí)地做到,但是應(yīng)該具備這樣一種精神。用更容易理解的話來(lái)說(shuō),就是要做到手中有劍心中無(wú)劍(請(qǐng)注意這跟武俠小說(shuō)上的說(shuō)法是反的-_-!)結(jié)論,既然都語(yǔ)言無(wú)關(guān)了,當(dāng)然沒(méi)有勝負(fù)之說(shuō)。
維護(hù)期。 OK,這實(shí)際上是一個(gè)軟工項(xiàng)目中生命周期最長(zhǎng)的階段。這里涉及了很多東西,最主要的就是3個(gè)方面:調(diào)試、維護(hù)、復(fù)用。這三個(gè)議題每一項(xiàng)都可以大書特書再書還要書。既然是生命期中最長(zhǎng)的一個(gè)階段,因此c對(duì)c++的重量級(jí)攻擊放在這里當(dāng)然就會(huì)很有效果。在維護(hù)上的代價(jià)而言,結(jié)構(gòu)過(guò)程化的c比抽象對(duì)象化的c++便宜太多了。這是“結(jié)構(gòu)過(guò)程化”與“抽象對(duì)象化”的根本不同所造成的差別。用程序員們更能夠理解的方式來(lái)說(shuō),c就像一個(gè)鏈表,要增減head很方便;而c++就像一個(gè)動(dòng)態(tài)數(shù)組,要insert[0]或者remove[0]就要牽一發(fā)而動(dòng)全身!但是,c真的就很好維護(hù)么?非也!一個(gè)瘋狂使用#define的c程序,不會(huì)比一個(gè)濫用oo特性的c++程序更好調(diào)試和維護(hù)。因此,這仍然是與開發(fā)期工作的質(zhì)量息息相關(guān)的。結(jié)論,好吧,我不得不說(shuō),在我眼中c和c++仍然不分勝負(fù)。
綜上所述,c和c++在我眼中不分好壞,具有同等的地位。他們分別代表了兩種不同的編程思想。 “結(jié)構(gòu)過(guò)程化”的c帶來(lái)的好處是賦予程序員更為強(qiáng)大的控制力,和維護(hù)期可以“斷章取義”的靈活性——但是代價(jià)是更多你不得不親歷親為的工作。 “抽象對(duì)象化”的c++帶來(lái)的好處是更為貼近現(xiàn)實(shí)的思維要求,以及更具親和力的“人機(jī)交互接口”——當(dāng)然,代價(jià)是需要你練好足夠的基本功來(lái)了解c++在背后到底做了些什么,以及在維護(hù)期和復(fù)用階段你可能要面臨的“抽筋”式的痛苦。
作為一個(gè)擁有美好愿望的程序員,我希望有一種語(yǔ)言,既能給我c的強(qiáng)大控制力和維護(hù)期的靈活性,又能給我c++的親和力和強(qiáng)大的——好吧,我承認(rèn)我比較喜歡template那種拐彎抹角的東西——腦力訓(xùn)練(—_,—),然后,又能輕易地滿足KISS的原則——這將可以讓我非常簡(jiǎn)單地找到高質(zhì)量的合作者 ——畢竟怪物級(jí)的c/c++程序員不是像現(xiàn)在的本科生一樣遍地都是。而且基于c/c++的靈活性——這里叫做不確定性更好——這一特征,每個(gè)怪物級(jí)的 c/c++程序員都有很大可能不能跟另一個(gè)怪物互相咬合他們腦袋里高速轉(zhuǎn)動(dòng)的齒輪——如果你非要那么做,這很可能會(huì)帶給你更多的機(jī)會(huì)讓你的項(xiàng)目走火入魔,甚至停擺,最后以自爆收?qǐng)觥?br>
但是遺憾的是,目前這只能是一個(gè)美好的愿望而已,我不得不采取折中的辦法來(lái)找一些代替品。因此,目前我的做法是,用c的規(guī)則來(lái)寫c++的程序,略微地用一些可以被我完全控制的c++的特性(模板的編譯期編程技術(shù)很贊,可以為運(yùn)行期的效率和正確性帶來(lái)很大的好處),最根本的出發(fā)點(diǎn)是建立在獲得強(qiáng)大控制力和可預(yù)期的維護(hù)期工作量的目的之上的,當(dāng)然,還有不能忽視的效率問(wèn)題——我的目標(biāo)是一個(gè)可擴(kuò)展的游戲引擎。
胡言亂語(yǔ)了一堆也不知道說(shuō)了些啥……最后做個(gè)總結(jié)性發(fā)言吧:c和c++都不是什么好東西,但是正如windows也不是什么好東西一樣,我們卻非得要用它們——至少在可以預(yù)見(jiàn)的一段不會(huì)算短的時(shí)期內(nèi)。
另外,撇開c/c++的比較說(shuō)點(diǎn)跑題的話。
c++目前確實(shí)處于一個(gè)相當(dāng)尷尬的境地,高不成低不就,過(guò)于復(fù)雜龐大的身軀又成為了他能夠被更熟練掌握的門檻。c++目前有兩條路可走,一是朝c退過(guò)去,二是朝更高之處攀登。但是無(wú)論走哪一邊,都是“強(qiáng)敵環(huán)視”,要想闖出一片新的天空,恐怕需要?jiǎng)ψ咂h了。至于是不是一定要偏著走,偏又要怎么個(gè)偏法,我也說(shuō)不出個(gè)所以然來(lái),且讓我們拭目以待吧。而c,很可能將會(huì)止步于“硬件受限”的時(shí)代吧,然后在這個(gè)時(shí)代和環(huán)境下再一點(diǎn)一點(diǎn)地進(jìn)化,最終與c++將來(lái)的終點(diǎn)完全分道揚(yáng)鑣。
個(gè)人以為,程序語(yǔ)言的發(fā)展以后將會(huì)明確地分出兩個(gè)方向,一個(gè)是以c為代表的“底層親和”的語(yǔ)言,它們的特點(diǎn)是將給于程序員最大的控制能力,讓一切盡在程序員的掌握之中。另一個(gè)將是以不斷發(fā)展的新興高級(jí)語(yǔ)言為代表的方向,也可能是c++以后的方向,它們的特點(diǎn)是不斷地將底層的東西從程序員的眼前隱藏起來(lái),讓程序員的門檻降得更低,充分地體現(xiàn)出KISS原則,并從而提高生產(chǎn)力和生產(chǎn)效率。
人類的知識(shí)累積將隨著時(shí)間的流逝慢慢增長(zhǎng),如果沒(méi)有一種有效的途徑讓后來(lái)者可以從更高的地方起步的話,光是學(xué)習(xí)就足以耗盡人的一生了。因此我認(rèn)為,“隱藏底層的東西”,將成為今后應(yīng)用軟件技術(shù)發(fā)展的關(guān)鍵,說(shuō)白了就是讓程序員傻瓜化。
本是同根生, 相煎何太急. C/C++本來(lái)就是用來(lái)開發(fā)系統(tǒng)級(jí)應(yīng)用的, 有何必強(qiáng)分彼此呢?
在程序開發(fā)中, 最重要的根本就不是語(yǔ)言,而是設(shè)計(jì)(在這點(diǎn)上面, Linus說(shuō)得是對(duì)的).
之后的問(wèn)題: 效率, 重用, 擴(kuò)展等等問(wèn)題都取決于你的設(shè)計(jì)和軟件的要求. 這個(gè)并不存在絕對(duì)的標(biāo)準(zhǔn). 說(shuō)C++開發(fā)不好的兄弟們, 請(qǐng)考慮考慮, 如果你用C改寫同樣的軟件, 你可以保證寫出來(lái)的軟件質(zhì)量就一定好過(guò)用C++寫的?
c/C++當(dāng)然存在個(gè)自適用范圍的情況, 一般認(rèn)為C比較適合OS內(nèi)核和遷入式的開發(fā). 而C++一般不太適合在這兩種環(huán)境下面. 這個(gè)原因是很多的, 其中很重要的一個(gè)原因是由于C++的OO特性會(huì)產(chǎn)生不必要的負(fù)載(其實(shí), 如果軟件設(shè)計(jì)得當(dāng)?shù)脑?加上一個(gè)合適的編譯器, 這個(gè)并不是很大的問(wèn)題. 在這裡,就假定C++不適合這些領(lǐng)域). 但是做游戲領(lǐng)域呢? 圖形介面領(lǐng)域呢? C++就非常合適(而C在這裡就顯得麻煩了). 兩種語(yǔ)言都有長(zhǎng)處和不足.
C++由于提供了太多的內(nèi)容(OO/模板/泛型...), 導(dǎo)致了大家有太多的選擇, 結(jié)果在軟件設(shè)計(jì)的地方錯(cuò)用了C++的特性, 導(dǎo)致了軟件的各種問(wèn)題(效率差, 不可擴(kuò)展等等). 這個(gè)是設(shè)計(jì)的問(wèn)題, 而不是語(yǔ)言錯(cuò)誤. 不要把自己的設(shè)計(jì)缺陷推到C++上面, 然后反過(guò)來(lái)指責(zé)C++. 老實(shí)說(shuō), 這樣的設(shè)計(jì)水平, 用任何語(yǔ)言都做不出來(lái)好的軟件.
至于Linus說(shuō)的C++是垃圾之類的話, 不用去當(dāng)真. 他開發(fā)出了Linux, 是很好. 但不表示他說(shuō)的話就是真理. 我相信那只是爭(zhēng)論時(shí)候的激憤之言(而且有特定的環(huán)境, 某位老兄批評(píng)了一把他寫的git軟件, 有點(diǎn)小器). Linus是人, 不是神. 用不著頂禮膜拜.
軟件質(zhì)量取決于設(shè)計(jì)而不是開發(fā)語(yǔ)言.
posted on 2007-09-11 22:28 lovedday 閱讀(1143) 評(píng)論(2) 編輯 收藏 引用 所屬分類: ▲ C Program