既然 C++ 是 C 的超集,為什麼還是有不少人認為 C++ 不如 C?
問題的意思是,如果不考慮 C++ 的某些高級特性和複雜性,僅僅用 C++ 按照 C 的方式寫程序,他們的差距在什麼地方?
不是超集就好用的。說C++不好的,從來沒有說它能力弱的,只是抱怨功能太多,用起來太亂太麻煩,而且還容易有歧義。
你在家拿臉盆喝水么?
=================
這樣的辯論是沒有意義的。因為別人可以說:你洗臉也用碗嗎?超集之說只是描述了C++和C的沿襲關係,C++向前兼容C. 但是使用兩個語言的指導思想、代碼風格、設計思路等等是完全不同的,可以認為是兩個不相干的語言,粉絲互噴也屬正常。
我用了五六年C++了,感覺最大的問題是C++太複雜。------------------------------------------------------------------------------------------------------針對補充說明再回復下。假設C++是一把瑞士軍刀,包含了水果刀的功能,你會只把它當水果刀使嗎?更大的問題是還不如水果刀好用。按照C的方式寫出來的是C程序,哪怕擴展名用的是cpp分類一下所謂不少人:
會c但壓根沒用過c++的跟風黑
會c++,但用c++寫著c代碼的,後來轉而直接用C的
用著腳本,但發現用c++寫腳本擴展要比c麻煩一些
在項目中濫用c++里的模板元,泛型想提高逼格,但最後發現搞不定而叛逃的(以前遇見過真實案例)
不知道RAII,被內存管理拆磨過的
被stl嚇跑的c程序員
大部分回答在比較C和C++的語言特性,但是,語言的應用場景在我看來才是最關鍵的因素。語言的所謂」複雜特性「其實能有多複雜呢?又不是讓你寫編譯器。語言設計者已經挖空心思盡量簡單一致地呈現特徵了,否則這兩門編程語言怎麼會流行?在這兩門語言最擅長也最常見的系統編程中,難題大都來自系統本身,和語言真心沒關係,C夠用了,C++更擅長泛型。回到你的具體問題,這兩門語言有差別,往細說挺多的,但真正的難題比語言差異難多了,所以它倆的差別可能是茶餘飯後的聊資,也可能是無病呻吟的借口。
(補充:除了專業的編譯器編寫者,大部分程序員不太重視語言的類型系統,而這正是一個語言的本質,這話怎麼說?語言編寫的程序運行起來後其實和語言本身沒什麼關係,通俗地說,都是跑的機器碼,語言的痕迹很淡。那我們在談」語言差異「,描述語言的」語言」到底是什麼?就是類型。類型和類型間的變換定義了語言,類型是比語言更高階的「語言」,語言的演變就是類型的演變。而C++一直想在不妥協性能的前提下提供更好的類型系統,在這點上C++一直活躍,也做的很不錯,所以C++11中才會出現auto,lambda等等特性。而C在類型系統上已經」死「了,換句話說,這就是一門「死」語言。死 vs 活,保守 vs 活躍,回顧 vs 學習,我想這是產生很多話題的源頭吧)C
「A C program is like a fast dance on a newly waxed dance floor by people carrying razors.」 - Waldi Ravens. Programmer.一段 C 程序,就像某人手拿剃刀,在剛打蠟的地板上跳快舞。—— Waldi Ravens(程序員)「In My Egotistical Opinion, most people』s C programs should be indented six feet downward and covered with dirt.」 - Blair P. Houghton. Programmer.依我自我的觀點來看,大多數人的 C 程序應當縮進 6 英尺,並蓋滿了灰塵。—— 布萊爾·霍頓(程序員)「Going from programming in Pascal to programming in C, is like learning to write in Morse code.」 - J.P. Candusso. Programmer.從 Pascal 編程轉到 C 編程,就像是在學用摩斯碼寫程序。—— J.P. Candusso (程序員)「One of the main causes of the fall of the Roman Empire was that, lacking zero, they had no way to indicate successful termination of their C programs.」 - Robert Firth. Author of programming books.羅馬帝國崩潰的一個主要原因是沒有「零」,他們沒法表明他們的 C 程序已經成功執行完。—— 羅伯特·菲爾斯 (編程書作者)「Writing in C or C++ is like running a chain saw with all the safety guards removed.」 - Bob Gray. Author.用 C 或 C++ 寫代碼,就好像在沒有保護設施的鏈鋸上奔跑。—— 鮑勃·格雷(作家)
「It』s 5.50 a.m…。 Do you know where your stack pointer is?」 - Anonymous.現在是凌晨 5:50…… 你知道你的棧指針在哪兒么?—— 無名氏C++「C makes it easy to shoot yourself in the foot. In C++ it』s harder, but when you do, you blow off your whole leg.」 - Bjarne Stroustrup. Creator of C++.C語言可以讓你容易用槍打到自己的腳;而C++則更不容易打到腳,但如果你硬開槍,則會轟爛你整個腿。 —— Bjarne Stroustrup「The evolution of languages: FORTRAN is a non-typed language. C is a weakly typed language. Ada is a strongly typed language. C++ is a strongly hyped language.」 - Ron Sercely. Programmer.編程語言進化過程:Fortran 是一種無類型的語言;C 是一種弱類型語言;Ada 是一種強類型語言;C++ 是一種高度言過其實的語言。—— Ron Sercely「I invented the term 『Object-Oriented』, and I can tell you I did not have C++ in mind.」 - Alan Kay. Creator of Smalltalk.我發明了「面向對象」這個術語,我也可以告訴你,我腦子中並沒有 C++。—— 艾倫·凱(Smalltalk 語言創造者)「The latest new features in C++ are designed to fix the previously new features in C++.」 - David Jameson. Author.
C++中的最新特性就是用來修正之前的新特性。—— David Jameson「Fifty years of programming language research, and we end up with C++ ?」 - Richard A. O』Keefe. Computer scientist.五十年的編程語言研究,我們在 C++ 這結束了?—— Richard A. O』Keefe(計算機科學家)「C++ has its place in the history of programming languages. Just as Caligula has his place in the history of the Roman Empire.」 - Robert Firth.在編程語言的歷史中,C++ 有其地位。就如同 Caligula 在羅馬帝國歷史也有其地位。—— 羅伯特·菲爾斯(譯註:Caligula 是羅馬帝國第三個皇帝,是個暴君。)「Java is C++ without the guns, knives, and clubs.」 - James Gosling, co-inventor of Java.Java 就是沒有槍支、刀具和棍棒的 C++。 —— 詹姆斯·高斯林(Java 之父)「C++ is an horrible language. Even if the choice of C were to do *nothing* but keep the C++ programmers out, that in itself would be a huge reason to use C.」 - Linus Torvalds, inventor of Linux.C++ 是一種恐怖的語言。
(譯註:Linus 這事情的起因是這樣的:2007年,微軟的一名工程師Dmitry Kakurin在查看了Linus 專為Linux內核開發的版本控制軟體 Git 源代碼之後,發現使用的是純 C 而非 C++,表示不能夠理解這種做法,他直言:「別拿可移植性說事兒,這是屁話(BS,bullshit)。」 )摘自站長之家http://www.chinaz.com/news/2012/0524/253696.shtmlC語言作為一個語言不在任何意義上比C++好。
----修訂----但是C有幾個決定性的優勢:- C沒有C++的ABI問題
- C的生成代碼尺寸可控
---修訂結束---
C++提供了重要的抽象手段,這些手段被證明對於工業化代碼生產是必須的,這裡面至少包括范型、數據抽象、面向對象、異常、RAII等。
正是C++提供的上述設施,是的如同C/C++這樣的Native的、靜態類型的傳統系統編程語言,竟然有了生產通用的程序庫的可能,這是在C裡面從來沒有做到的,C雄霸計算機界幾十年,坐擁最優秀的人才,最龐大的人力,到如今,幾乎每個C工程都必須為自己準備或定製基礎數據結構設施,這不是沒有原因的,其原因就是,C在這個方面完敗給了C++,C語言就不是一個可以製作通用數據結構庫的語言。
哪怕只是為了使用STL,在可能的情況下都應該使用C++,而不是C。
C++的C部分,一般來說,也比相應的Ansi C更好,有更強的類型檢查,更方便的類型檢查,更方便、明確的初始化語義(是std::fill(blabla)還是memset(blabla)好?更何況後者很可能還不正確)。
C++提供的數據抽象和面向對象的支持,在這幾十年中,被幾乎所有的後來者沿用,新興的工業語言C#/Java,沒有一樣不是以類似C++的方式提供這些東西的,並且只有在C++裡面,這些東西是以不帶來額外代價的方式提供的。
關於C++比C性能差的說法幾乎總是胡說八道,沒錯,虛函數總是比直接的函數調用慢,但是,直接的函數調用和虛函數不是一樣的功能!在C裡面,這可能需要根據某種類型標識去分派,或者使用函數指針,這不僅並不比C++快,而且無論以何種審美觀來看,都不如C++的方式優雅。
有的人會爭辯C++提供的功能實際上是不被需要或者不太被需要的,這太霸道和傲慢了,如果C程序員從來就不需要那些東西,C裡面就不會出現那麼多模擬動態綁定、面向對象、范型等C++特性的所謂idioms了,正常審美觀的人不會認為把數據和函數指針放在一個struct裡面模擬數據抽象比C++的方式好。
C++在某些方面,甚至比人們想像的更好,比方說因為RAII的存在,C++裡面的異常安全要比其他語言容易一些,正是因為這樣,C#引入了using (){}這樣的形式,Java引入了try-with,Python加入了with,這都是學習C++的RAII,但無一例外比C++的要差。
當然,C++也有一些問題,比如標準庫不夠好,沒有memory model,一些語言特性不夠明確,比方override不是明確的,而C#就以override關鍵字明確了其行為,異常不夠好用,沒有語言級別的stacktrace等等。但在這些缺點上,C總是比C++走的一樣遠,如果不是更遠的話。C 不是C的超集
這是兩種不同的語言
因為他們覺得C已經能解決他們所有問題了,他們不想再學習新的語言。如果可以,他們也不想再學什麼新東西了。
噓,其實我一直認為,那些覺得學習C++太折騰而堅持用C的人,(編程中)真是太能折騰了。(考慮C比C++還要簡陋得多的標準庫,字元串處理,手工的內存管理,沒有模板等抽象手段,沒有確認的構造析構,等等等等)
我唯一覺得C比C++有優勢的地方就是C語法簡單得多,所以編譯器容易實現,在新硬體平台上有可能可以更容易更完善的得到支持,而且寫工具處理 C 代碼會容易很多,所以相對容易做開發的輔助工具。不過我覺得這個在編譯器框架越來越進步的未來,這樣的優勢會越來越不明顯。
那些用C的人在語義之外關心了太多的東西,導致他們面對C++的時候,感覺就像讓你用集合論來定義一個經典幾何的題目然後解出來一樣,是不是很難受?
這叫活該他們用C語言,把明明可以用來把妹、滴蠟、母女丼等那麼一大段時間,都用來找「他媽到底裡面做了什麼事情」。你以為編譯器那麼好寫啊,隨便看一段程序你就要知道他裡面到底如何去manipulate那些bits?這也只有C語言能這樣了,別的語言根本沒有這種機會。你們用C#、python、javascript的時候會去關心它們是如何manipulate那些bit嗎?
執著太多,徒增煩惱啊,只關心語義就行了,這樣你們就有大把的時間來玩母女丼了。
贊同 @pansz 的回答。
我來吐槽一下。學校當年毀人不倦,無任何編程基礎上來就教C++,還沒弄清楚什麼是堆什麼是棧呢,繼承重載多態模板就來了,我們可不是LInus,Carmack這些玩著電腦長大的孩子。1,學習成本:即使有經驗的C++程序員仍會濫用語言的某些特性(比如模板)。實際反映出語言的臃腫複雜甚至是設計缺陷,直接導致學習路線陡峭。一般學生/工程師只要認真的學完 200 頁的《KR C》就能把 C 用起來,對應 C++11 版本的《The C++ Programming Language》已經 1200 多頁了。用現代的 C++ 設計一個類我先要考慮五類函數(rule of five)寫還是不寫、怎麼寫,這是我無法承受的負擔。
2,適用性:C++多數特性是為大型工程準備的:面向對象、模板。他在需要多人團隊開發的 high performance 大工程中確實比 C 更有優勢:便於設計,代碼可讀性強易維護。而如果我的問題幾十個函數,幾個.c文件就能解決我何苦去浪費時間學習 99% 用不到的特性呢。3,兼容性:C++的ABI兼容廣受詬病,各廠商編譯器實現差別大。而C才是真正的工業標準。問題不成立,C++不是 C 的超集,雖然在設計 C++ 的那個時候(幾十年前),C++ 被設計為當時 C 的超集,但 20 多年過去了, C++ 跟 C 的標準經歷了兩條不同路線的變遷,兩者已經發展成為並不互相兼容的兩套不同語言。
如果用 C 的方式使用 C++ ,就意味著你必須按照 20 甚至 30 多年前的 C 語法去寫程序,這並不會是愉快的體驗。
如果把時間倒退到幾十年前,這個說法是否就成立呢?也不完全成立,因為 C++ 那時從語法上雖然是 C 的超集,但一段用 C++ 編譯器編譯的,用 cpp 後綴寫的 C 代碼,生成的會是跟 C 語言完全不同的目標代碼,這種目標代碼與 C 語言並不是二進位兼容的,甚至不同的 C++ 編譯器之間也無法兼容(不同的 C 編譯器編譯的目標代碼通常可以互相調用,而 C++ 不可以)。這又引發了 C++ 的另外一個長期被人詬病的問題:ABI 兼容性問題,有興趣的可以仔細研究一下。
更多的時候,這種爭論是沒有意義的,很多 C++ 程序員並不真的懂 C,反之亦然,如果還停留在認為 C++ 是 C 的超集這種錯誤假設上,那麼互噴對技術沒有促進,僅僅只是口水戰而已。首先,很負責任地說, C,CPP只是語法相同而已;編譯原理完全不同!!!這就是很多高手說著C,CPP不同的根本地方。而其他人說著說著卻說不清楚。
其二,對比起C,CPP的確增加了面向對象編程。 但是CPP的繼承,多態操作符重載等語法,比起java甚至python,真的要多麻煩有多麻煩!的確,麻煩的語法意味著強悍的性能(CPP還能嵌asm呢),但就增加了學習的難度了啊。
其三,內存泄露問題。這個不多說~中英文 mix 的 style 是中文的 superset,why 有人說是裝逼呢?
1.這其實就是一個「什麼都沒有,就是什麼都有」的哲學問題。2.c相對於c++,可以說什麼都沒有;同樣也沒有能夠被人抓住把柄的東西;3.c++提供的特性多了,被人詬病的東西同樣也就多了。4.c++本身不是不好,她是命不好,生在c後面。
性能上姑且不論,就單從設計上來說,有的時候,功能多了反倒成了累贅,也就是
所謂"心智包袱".比如我要實現一個運行期統一介面地調用根據對象的不同而改變的函數,在C語言里,我可能思考1秒鐘,然後想:"恩,使用函數指針",而在C++里,我的思維可能是這樣的:"恩,我用函數指針吧"..."等等,用虛函數最好了"..."哦,或許這裡我該定義個基類"...
"我知道了還是用模板最好"...."等等匿名函數似乎未來擴展性更強點"..."STL里有個和剛才一個函數類似的功能,或許我該"...."我知道了用模板元在編譯器解決一下這個問題..".....有時候這樣真的很煩,尤其是結構比較複雜的時候,經常設計了一整天結果發現更好的設計(事實上你總能找到更好的設計),而C簡單明了,一個需求只有一條路能幹.
當然,這樣也不是不好,好處就是你能幹一切...C++11+boost之後更是如此了不懂前面的人對於C++的抱怨,C++作為C的超集,但是現在已經不完全兼容C了,C簡單明快,控制力強,是一門好語言,相對,就算同樣的代碼,在C++中實現,也會產生很多問題,會導致一些意想不到的結果。C++確實很複雜,確實很臃腫,什麼特性C++都能夠摻一腳,但是又都沒有做到很好,簡單舉個OOP,C++默認函數定義不是virtual的,其實是一個很大的問題,寫多態的時候,數組又不支持多態,有著太多的坑點,更加別說函數式編程什麼的,都是非常非常多的坑點。但
是,我不同意前面幾個前輩對C++的評價,覺得第一門語言學C++真的虧大了什麼的,覺得學校毀人不倦的,也不想想,學習C++的過程中,學到的東西比其
他任何一門語言都要多,同時學會了下層的內存控制,編譯器的堆、棧內存控制,上次的class結構,面向對象思想,多態,指針,不管是什麼,都已經開好頭
了,正像是師傅領進門,修行在個人,之後不管轉什麼語言,都非常方便(fp當我沒說……,C++的fp特性才剛加,而且我認為加的很糟糕……)。簡
單的總結下,學會了C++,雖然編程思路上還要重新習慣,但是不管是寫java or 寫c的學習成本,絕對比先學會java之後寫C++或者c
或者先學會c再學C++ or
java要快很多,這裡就拿這三門語言做例子,其實其他很多語言都非常相似,其實只要學會了C++的思考方式,就算是lisp或者是ruby應該也蠻快
的。
C++和C相比,哪怕同一段代碼,很有可能C++做了比C更多的事情,而這些事情是編譯器在背後做的,越是「所見即所得」,在代碼規模比較小的時候,控制代碼的表現比較容易,但是當代碼規模較大的時候,這種控制能力往往會成為一種累贅。
看了前幾名的答案,其實我也是基本贊同的,但是我覺得想補充一個之前大家沒有說到的問題:
如果我們用項目數量來衡量,那我們開發的項目,有多少是適合使用C++這麼語言的?究其根本,我覺得C語言長期盤踞開發人員使用的語言第一名是有原因的,因為從計算機擅長處理的問題角度出發,其實從數量上說,大多數項目並不算「複雜」,即使像操作系統內核這樣的事情,其實嚴格算起來,其複雜度更多在於如何更加高效、穩定的使用計算機的硬體,而計算機硬體本身實際是不太複雜的,是天生有線性特性的。這種「不複雜」的場景,用C語言是足夠的。
而對於「模擬人生」這類處理非線性事件,C語言就不太合適了,究其原因我想無非就是C語言的「線性思維」無法直接在這種非線性情景中快速的進行映射,相比而言,擁有「面向對象」等高級特性的C++語言(當然其他擁有同樣特性的語言,如Java也是一樣的)就相對容易建立這種映射。說 C++不如 C 的原因在於可以替代 C++ 工作的語言很多,而可以替代 C 工作的語言有多少?也就說語言的可選性多了導致的。
1,C++太過龐大,可能是特性最多的語言了,妄圖在各種編程範式都插一腳,程序員很難完全掌握,因此在沒有約束的情況下,不同的C++程序員寫出的代碼,可能用到了C++不同的語言特性,比較難以互相理解。2,C++編譯器背著程序員做了很多事情,很多情況下,會造成難以調試的bug。3,C++各編譯器之間兼容性沒有C強。以上之外,還有一個,C++實在是學得太痛苦了,完全抹殺了程序員開動大腦時的樂趣。
推薦閱讀:
※為什麼 C# 的語法特性並不比 C++ 簡單,但編譯速度卻比C++快那麼多?
※學C++真的需要看那麼多書嗎?
※既然建議盡量避免使用goto語句為何C++還要支持goto呢?
※c++ ,如何按照不同的要求調用標準庫sort函數排序?
※在C#中,如何實現跟native dll 中途的線程間通信?