Objective-C 和 C++ 的區別有哪些?為什麼蘋果會選擇前者?
這麼說吧,寫objc的時候我可以邊寫一邊感慨
「這裡要是CPP就簡單了……」
「這裡要是CPP就不用重複了……」
「這裡要是CPP就可以直接靜態化不用反覆載入了……」
……
真寫CPP的時候根本沒時間去比較,都是一邊寫一邊哭著問編譯器「我他媽到底錯哪兒了你說清楚啊!」可以從歷史角度看看。
先看Objective-C
1980年代初Brad Cox和Tom Love在公司Stepstone發明。
1983 年,Cox 與 Love 合夥成立了 Productivity Products International(PPI)公司,將 Objective-C 及其相關庫商品化販售,並在之後將公司改名為 StepStone。
1986年,Cox 出版了一本關於 Objc 的重要著作《Object-Oriented Programming, An Evolutionary Approach》,書內詳述了 Objective-C 的種種設計理念。再看C++
1983年,在C語言基礎上貝爾實驗室的Bjarne Stroustrup推出了C++
1985年公布的的C++語言1.0版的內容中又添加了一些重要特徵:虛函數的概念、函數和運算符的重載、引用、常量(constant)等。
1989年推出的2.0版形成了更加完善的支持面向對象程序設計的C++語言,新增加的內容包括:類的保護成員、多重繼承、對象的初始化與賦值的遞歸機制、抽象類、靜態成員函數、const成員函數等。最後看Objective-C的主推喬布斯的NeXTSTEP
Objective-C的歷史遠比C++久,喬布斯1985剛從蘋果公司攆出去,準備捲土重來二次創業。C++ 85年才出了1.0,喬布斯建立NeXTSTEP時,估計還不知道C++是個什麼玩意,而Objective-C 83年就有比較成熟的商業產品了。要你肯定也選Objective-C,不會選C++。
NeXTSTEP Steve Jobs在1985年離開蘋果計算機後所創立的公司。
NeXT獲得了Stepstone公司的Objective-C語言授權,並擴展了著名的開源編譯器GCC 使之支持 Objective-C 的編譯。並基於 Objective-C 開發了 AppKit 與 Foundation Kit 等等庫,作為 NeXTSTEP 的的用戶介面與開發環境的基礎。
第一個版本 0.8 1988年10月12日發布當年喬布斯還在蘋果公司,帶隊到施樂公司參觀。施樂公司演示了三項成果,一是計算機之間如何聯網,二是面向對象編程語言 SmallTalk, 三是圖形界面。
當時蘋果公司竊取(或借鑒)了圖形界面,推出了 Macintosh。之後喬布斯離開蘋果,開了 NeXT 公司,間接竊取了另外兩項成果。第一個萬維網(WWW)是伯納斯在一台 NeXT 工作站上開發的。而 NeXT 使用的 Objective-C 語言受 SmallTalk 影響很大。
之後蘋果收購了 NeXT 公司,喬布斯回歸。NeXT 的操作系統跟原 Mac OS 系統融合,演變成 OS X,NeXT 的 API 演變成 Cocoa。準確地說,並非是蘋果公司選擇了 Objective-C 語言,而是 NeXT 公司選擇了 Objective-C 語言。
為什麼呢?從時間上看,C++ 那時還不成熟。
從更深層次看,假如是做 UI 系統,Objective-C 要比 C++ 好。同是面向對象語言,C++ 和 Objective-C 是很不同的,面向對象也有分流派。C++ 的對象思想主要來自 Simula,更關心類的劃分,它的方法調用是完全靜態的。而 Objective-C 的對象思想主要來自 SmallTalk,更關心消息傳遞,對象之間可以動態地發送消息。在 Objective-C 中,對象不管是什麼類型,只要定義了某個方法,就能夠響應消息。面向對象更本質是消息,而不是什麼繼承、多態。Objective-C 的面向對象比 C++ 更加純粹。整個 UI 系統,實際上是不斷地響應消息,跟 Objective-C 的思想更加契合。
為了性能,C++ 編譯後是完全靜態的,運行時就沒有對象的存在。用 C++ 來寫 UI 是很麻煩的,常用兩個 C++ 的 GUI 庫,一是 MFC,基本已經死掉了。回頭看,當時覺得很精巧的宏,現在已不堪入目。另一個是 QT,而 QT 的 C++ 代碼並非標準的,QT 添加了預處理器,編譯時為 C++ 添加了某些動態特性。
上面的討論說得比較簡略,更詳細可以參考這篇文章function/bind的救贖(上)。
用 Objective-C 編寫的 Cocoa 框架發展到現在,差不多 20 年了,居然沒有一點老態,還是很現代的。人們說 Objective-C 不好,只會說語法怪異,但幾乎沒有什麼人說 Cocoa 框架設計得不好的。現在換成 Swift 語言,很多框架還是原來的框架。
網上摘的:
開發人員為何應該使用 Mac OS X 兼 OS X 小史
by 徐宥 http://blog.youxu.info/2010/02/28/why-mac-os-x-for-programmers/
在內核層面,他們用了 Mach 這個為 BSD 設計的微內核。
這個操作系統內核就是為了替換已經過時的 UNIX
內核而設計的,
其中的一個核心設計哲學就是重新設計進程間通信;
雖然現在基於微內核的操作系統已經不是什麼潮流(為此 Linus 和
Tanenbaum 吵了一場著名的架),
但在相比較於當時 UNIX 系統的內核
(此時 Linux 還沒出現的,UNIX 內核只有 BSD,
Bell, SUN 等幾套),
Mach 算是一個高的起點。在這個內核上,Next 公司的工程師開始構建面向對象的基礎系統。
這套系統在
Smalltalk 中已經有了藍圖,
因此這些工程師以 Smalltalk 為藍圖,先設計了一套基於 C 的語言,
也就是 Objective
C,照搬了 Smalltalk 的經典的 [對象 消息: 參數] 語法。
(我個人不喜歡 Objective C 這個語言,
Smalltalk 是一種純面向對象的動態類型的語言,Next 公司當年完全有機會用
Smalltalk 語言的,
如果用了 Smalltalk,現在的 Cocoa 框架還會更加漂亮,代碼更加乾淨;
用 Objective C
這個自創的語言,不知道是不是因為專利的考慮,
反正 Objective C 這20年的所有創新,就是在慢慢的更像 Smalltalk
而已,
Java 和 Ruby 這幾年也是不斷的從 Smalltalk 拿東西)。首先是兩者的應用範圍, Objective-C主要的應用範圍是寫GUI程序, 而C++的應用範圍要廣的多.
然後, 兩者從編程語言的角度來說是完全不同的設計思路, 除了名字里都帶個C之外, 基本沒有什麼共同點, Objective-C更偏向與動態語言, 比喻的話, 可以理解為需要寫Type annotation的Python.
Objective-C本身具有很多適合寫GUI程序的特性, 比如說強調類與類組合而不是繼承, 開放的Class, 利用Protocal做契約約束, 有反射的機制等等. 這些語言特性 相比較與C++, 在寫GUI方面有很大的優勢. 如果不信的話, 可以看看當年MS的COM, 很好的設計理念結果通過C++表現成什麼樣子.
所以我覺得蘋果選擇Objective-C是因為很了解自己要選擇的這門語言的應用範圍, 不需要一個大而全的語言, 只需要一個方便寫GUI的語言. 此外, Objective-C只是蘋果在Cocoa/Cocoa touch層使用的語言, 主要面向第三方開發者, 所以簡單易學生產效率高也是一個需要考慮的因素, 而Objective-C也很好的滿足了這幾個要求.
IOS下的編譯器clang是C++開發的:Clang and LLVM clang: a C language
family frontend for LLVM. All of the LLVM
tools and libraries are written in C++ with extensive use of the STL.針對LS某些說蘋果厭惡C++的人
關於Objective-C 和 C++的區別這個文檔有很詳細的說明 http://chachatelier.fr/programmation/fichiers/cpp-objc-en.pdf
兩門語言雖然同是C的超集,但是它們實現面向對象特性的方法很不一樣。個人覺得Objective-C中最重要的概念不是「對象」,而是「消息機制」,弄懂了「消息」基本就明白兩者的區別了。
Objective-C是一門在C的基礎上加了一層非常薄的面向對象支持的語言;而C++是一門全新的計算機編程語言,幾乎支持所有的市面上可見的編程範式,然後,它兼容C。Objective-C是C的擴展,設計思路上借鑒了Smalltalk的面向對象和消息機制的思想。從我個人使用過的面向對象語言來看Objc是對消息傳遞支持的最徹底也最顯式的。其它的C++、Java、Python、Ruby都體現的不明顯,更傾向於對象的封裝和抽象。
Objc和C++基本上是兩門語言,沒有太大的關係。Objc本身是靜態語言,編譯後就是機器碼,執行效率很高,但引入了很多類似Python、Ruby的動態特性,像動態類型推斷,id,selector,block等特性,所以又非常靈活。用慣了Java或C++會覺得Objc的語法很怪,但是放空自己去學習這門語言的話,你會很快愛上它的消息式的編程風格,加上強悍的XCode,無論是寫mac應用還是ios應用,都會非常得心應手。
學習Objc不需要有c的背景,倒是學Objc的時候順手可以把C也學了或溫習下,由於Ojbc是C的超集,所以在Ojbc環境執行C程序毫無問題。關於蘋果為什麼採用Ojbc的問題,說明一下,其實不是蘋果採用了Objc,而是喬布斯創建的Next公司的操作系統NextStep採用了Ojbc作為原生語言。NextStep是以Mach和BSD為基礎,Objc是其語言和運行庫,後來的事大家都清楚,蘋果買了NextStep,喬幫主回歸,NextStep也成了Max OS X的基礎。以後發展越來越好,Objc反而成了Apple的當家語言,現在基本上是Apple在維護Objc的發展。
還有一點不要忘記,第一台萬維網的Server就是一個叫蒂姆·伯納斯-李的大牛在NextStep上寫的,包括瀏覽器。所以,咱們得感謝Objc,要不然還不知道互聯網會發展成啥樣呢......這說明你看的不過是一本粗淺介紹語言入門開發的書。如果你想知道答案,建議你先看《 Master Mind in Programming 》里 Objective-C 和 C++ 設計者的 interview。如果裡面有不懂的概念就停下來 Google。如果你有決心,也可以先用一個月看《 The Deisng and Envoluation of C++ 》之後再看 Objective-C 設計者的 interview。
看到問題修改了,我也增加一些內容。Apple 為什麼選擇了 Objective-C 具體原因不可能準確獲知。不過 Jobs 本人似乎對 OO 有些了解。Apple 的程序員很厭惡 C++,曾經出過一個 Tech Notes 告訴 Mac OS X 開發者不要用 C++(後因為反對浪潮較大撤下)。這說明在 OO 方面,Apple 對 C++ 和 Objective-C 的異同應該很清楚。
我的一些分析,最近寫了一篇:http://techsingular.net/?p=1895我來做一個偏向實現的回答吧
C++的面向對象特性是由編譯器支持的,而且與其說是對C的拓展不如說是一門擁有C語法和部分特性的全新語言,C++不斷擴展的標準也和C產生了衝突,私以為C++注重的是功能性,即通過對語言特性的不斷拓展和修改來創造出功能非常全面的語言。現在C++的功能已經非常全面複雜了,但是由於語言設計的思路導致到現在為止C++都還是一個非常偏向靜態的語言,絕大多數的面向對象特性都在編譯階段由編譯器進行了實現。
Objective-C的面向對象實現是拓展C的,C代碼可以直接放在Objective-C程序里經過編譯。而且Objc本身的OOP實現是使用C結構體模擬的。
(我對於C++了解甚少,道聽途說,懇請各位大牛指正。)struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
}以上代碼是Apple早期的objc_runtime開源代碼,現在可能實現略有不同,但大體相似。
這樣一個結構體存儲了方法cache,方法鏈表,成員變數鏈表,超類等等信息。我們在objc里聲明類的語法在編譯器中會被轉化成這種C代碼。
而諸如[bar foo];之類的發送消息語法,在編譯階段會被轉換成一個對於objc_MsgSend方法的調用。比如objc_MsgSend(bar , @selector(foo));
注意編譯階段的檢查已經到此為止了,剩下的對象該怎麼回應這個消息已經被推遲到了運行期。
這個方法幹了什麼呢?它大體上上幹了這麼幾件事情:
1.查找bar這個objc_class結構體的cache里,看看有沒有常用的被cache的方法,找到-&>執行,沒找到-&>2.
2.查找自己的方法鏈表裡有沒有這個方法,找到-&>執行,如果常用就扔進cache里,沒找到-&>3.
3.找到自己的超類結構體,重複1-2.注意剛才敘述的一切都是在運行階段發生的,如果一直找到根類NSObject都沒有,那就只能拋出一個異常,告訴runtime"我處理不了這個消息"
而編譯期間編譯器是不知道的,clang會根據你導入的頭文件來判斷是否有這個方法,來阻止你編譯,但是如果你發送perfromSelector消息來讓一個對象處理消息或者直接使用objc_MsgSend發送,在編譯階段編譯器是一無所知的。
這樣做有什麼好處呢?首先結合objc的runtime可以實現很多動態特性,比如反射,因為在運行階段對消息的處理都是動態的,所以可以更改對象處理消息的方式,或是將處理不了的消息拋給其它對象。
還有諸如id類型id是一個指向 objc_object 結構體的指針,該結構體只有一個成員isa,所以任何繼承自 NSObject 的類對象都可以用id 來指代,因為 NSObject 的第一個成員實例就是isa
引用自羅朝輝 (http://ww.cppblog.com/kesalin)
壞處也有很多,比如錯誤使用或濫用動態特性會導致程序難以維護或產生不宜排查的錯誤。降低程序的可讀性(當然善用也會提高可讀性)
ORZ貌似說的有點多有點跑題,本人可能理解不夠深刻或有謬誤,懇請各位指正。
而且維護一個runtime也需要性能上的開支,因此非常依賴性能的引用不適合使用Objective-C的特性。(如同各位大牛所言,用來寫GUI程序很合適)
蘋果選擇objc是為了更好的控制這門語言,為己所用,隨意在語言特性中加入適合於自身開發需求的元素。如果選c++就不太行,沒有這個優勢這個老問題也不知道咋出現在時間線里了,就吐個槽吧,要回答這個問題兩個都要系統學過、認真用過吧,起碼對蘋果平台編程語言選擇的歷史也要有點背景知識吧……
論歷史,Objective-C 比 C++ 出現、成熟都要早,對象系統設計更接近 Alan Kay 當初的本意。但是,蘋果早年其實是選了 Pascal 的呀。歷史是這樣的:
- classic MacOS 是選了 ObjectPascal 做為官方應用開發語言滴。
- 而到了 90 年代中,大部分 MacOS 應用都是在 CodeWarrior 里用 C++ 寫滴。
- 2000年開始推出了 C++ 的應用開發框架 Carbon,這個當初可是 MacOS X 的首選框架,比如 Finder 一直到 2009 年才用 Cocoa 重寫了,當時也被視為 Cocoa 成熟的重要里程杯。
- 2007年 MacOS X 轉64位之後,Cocoa 就逐步取代 Carbon,這以後 Objective-C 才取代 C/C++ 成為主要平台開發語言。
估計國內 2007 年之前也沒多少 Mac 開發者就是了。
至於 Objective-C 其實是老喬在 NeXT 選的,他從 Brad Cox 和 Tom Love 創建的 StepStone 公司手上取得了該語言的授權,並從那邊挖來 Steve Naroff 負責擴展 GCC 以支持 Objective-C。1996 年蘋果收購 NeXT 以便把喬幫主弄回來,NeXTSTEP 於是成為後來 MacOS X 的開發框架。至於為啥,Why Objective-C?說得明白:面向對象、兼容C、簡單。相對 C++ 的話,最後一點上勝出。
因為C++之父自己都承認,C++不是一個面向對象語言。
知道這個你是不是覺得被課本坑了?http://www.stroustrup.com/oopsla.pdf蘋果用 Objective-C 而不是 C++ 有歷史原因也有編程語言本身的原因,就語言來說 Objective-C 比 C++ 更適合 GUI 編程。
先說歷史原因,蘋果今天的 OS X 和 iOS 來源於一個叫 NeXTSTEP 的操作系統,這個系統是喬布斯被趕出蘋果後建立了一個叫 NeXT 公司所開發的,後來蘋果以收購 NeXT 的方式讓喬布斯從新回到蘋果,NeXTSTEP 被改造後成了大家熟悉的 OS X 和 iOS。 NeXTSTEP 使用了 Objective-C 作為編程語言也一直延續到今天,SDK 里很多類的前綴 「NS」 就是 NeXTSTEP 的縮寫。NeXTSTEP 選用 Objective-C 是因為它誕生於 1980s, 面向對象編程是很新的概念,支持的語言很少,C++ 那時候雖然已經誕生但是還沒有標準,各種 C++ 實現之間存在很大差異,而 Objective-C 是 StepStone 公司的產品,並且很成熟,選擇Objective-C 成了很自然的事情。這是歷史原因。
再說說這兩個語言的本質區別,以及為什麼不選 C++。以蘋果的實力讓 SDK 支持一個編程語言是很簡單的事情(比如 Swift),為什麼蘋果不支持 C++ 呢?畢竟用流行的語言更容易吸引開發者和降低開發成本。這是因為對於開發 GUI 程序來說 C++ 缺乏必要的特性,編寫 GUI 程序需要一些動態特性,如果語言不支持這種特性那麼就要先把這些特性實現出來。主要有兩個特性:
- 根據類型動名態創建對象,UI設計一般是由專業的設計師通過設計工具完成,結果是一個UI的描述文件,例如 iOS SDK 的 xib、MFC 的 dialog resource、QT 的 QML,然後程序讀取這些描述文件生成UI,這要求語言要具備根據類型名字動態創建對象的特性。
- 動態判斷一個對象能處理的事件,GUI程序的運行是基於事件的,這就要求語言能動態的判斷一個對象能響應哪些事件。
這些特性 Objective-C 具備而 C++ 不具備,這就是他們的本質區別。MFC 為了能動態的根據類型名創建對象實現了 CRuntimeClass 和 DECLARE_DYNCREATE 宏,QT 用 QMetaObject 和 Q_OBJECT 宏還要結合特有的 preprocessor。在動態判斷一個對象對事件的響應上 MFC 提供了 BEGIN_MESSAGE_MAP END_MESSAGE_MAP 這樣的宏,然後需要手工的完成從事件到處理函數的映射,QT 為了能自動完成這個過程創造性的通過 preprocessor 給 C++ 增加了新的語法以支持 slot 和 signal!!!假如蘋果也支持 C++ 恐怕又要在折騰出一套東西來。所以蘋果選用 Objective-C 而不是 C++是一個正確的選擇。
其實蘋果不是沒選用大家熟悉的語言,只是這個語言是 Java,這個東西叫 Java bridge (Cocoa (API))。只是從 OS X 10.4 開始就廢棄了。只說一點:
至於其他更根本的東西……這樣的問題是沒意義的。凍豆腐和喜之郎果凍之間是什麼關係?
Objective-C 是一種動態的、重度依賴運行時的語言。相比 C++,Objective-C 為運行時確保程序不崩潰提供了更多的迴轉餘地。相同一個「發送錯誤消息」,Objective-C 可以允許你在運行時檢測到錯誤,而 C++ 直接給你編譯、鏈接時可能已經失敗了;如果萬一通過了鏈接,在運行時發生介面不匹配,程序的崩潰是根本無法處理和保護的。
對於面向對象的理解,相對於C++,objective-c更加強調的是對象間的消息傳遞。關於這點你可以搜一下objective-c的前輩smalltalk的發明者Alan Kay關於這方面的闡述。至於為何蘋果選擇objective-c作為開發語言,我想是因為應用程序都是事件驅動的,這符合objective-c的特性。首先,蘋果當初擴展 C 的背景,是為了方便開發 GUI 程序。
相比 C++ 而言,Objective-C 對 C 做的擴展並不多。它面向對象的方式,實現的是消息模型。動態靈活,適合實現 GUI 界面。
而 C++ 的特性,著實豐富得可以說過於複雜了。它支持多種編程範式,包括面向對象。不過,與其說 C++ 的面向對象編程是 object-oriented,還不如說它是 class-oriented.
題外話,C++ 的 QT 庫實現了 signal/slot 動態消息機制,與 Objective-C 可以說是殊途同歸。
我的理解是oc是獨家語言,而c++有標準委員會,屬於各操作系統的公共語言,想升個級什麼的相當麻煩(自行升級相當於不兼容),不升級等委員會n年才討論出一個新版本,市場根本不允許。如ARC功能在c++中不成熟,但在市場產品開發中相當重要,而java是別公司的不能用,c#是微軟的也不能用,python性能太差,光用c開發成本太高,所以一直在發展在obj-c。雖然語法受歷史影響有些怪,但這個控制權在於蘋果,而swift就是為了彌補語法和吸引java,c#,python,vb等開發者的糖果。
Masterminds of Programming(編程之魂)里有介紹:):)
推薦閱讀:
※「只要是微軟的 C++,都是不標準的,而且 IDE 龐大,C++ 11 的特性都沒支持全」是真的嗎?
※如何以「Hello World!」為腦洞如何展開一篇故事?
※怎樣使用 GitHub?
※學習編程需要安裝哪些軟體?
※C 與 C++ 誰的效率高,為什麼?
TAG:蘋果公司 (Apple Inc.) | C++ | Objective-C | 編程語言比較 |
