從C++轉向Objective-C
Objective-C中沒有多重繼承、命名空間、運算符重載、模板、類變量、抽象類、STL等結構。但是Objective-C提供了相似的結構。
C++虛表與Objective-C動態分配
C++與Objective-C的最大區別在於分配方法(C++中成為成員函數)的機制不同。C++基於虛表(vtable)機制確定虛函數調用什麼代碼。
可以認為每個C++對象都有一個指針,指向函數指針數組。
編譯器知道代碼需要調用某個虛函數後,它將從虛表的開頭計算便宜位置,並發送機器代碼使函數指針指向該偏移位置,然後執行該位置的代碼段程序。該過程需要編譯器在編譯時知道調用成員函數的對象類型(這就是為什麼寫C++代碼時,需要強制轉換一些類型),這樣才能正確計算虛表的偏移位置。這種分配非常快,只需要幾個指針操作和一個獲取函數指針的讀操作。
Objective-C使用運行時函數進入各種類型結構中查找相應的代碼以供調用。
這種技術比C++的路由要慢的多。Objective-C犧牲了一定的速度和安全,換來靈活性和便捷性。在C++中,因為編譯器可以確保對象能處理對應的方法,所以C++是非常安全的。但是缺乏靈活性。
這裡說一下isa指針,NSObject 中有一個Class isa 的指針類型的成員變量,因為我們的對象大都直接或者間接的從NSObject 繼承而來,因此都會繼承這個isa 成員變量,isa 在運行時會指向對象的Class 對象,一個類的所有對象的Class 對象都是同一個(JAVA 也是如此),這保證了在內存中每一個類型都有唯一的類型描述。這個Class 對象中也有個isa 指針,它指向了上一級的父類的Class對象。
在明白了這個isa 之後,你就可以明白在繼承的時候,A繼承B,你調用A的方法a(),首先A的isa到A的Class對象中去查找a()方法,找到了就調用,如果沒找到,就驅使A的Class對象中的isa到父類B的Class對象中去查找。
C++編譯器不再保留很多類信息,例如類的繼承鏈、類的成員等。通常,C++在運行時處理對象的能力是有限的,最多只能進行動態強制類型轉換。通過該操作,可以了解某個對象是否是另一個對象的指定子類。
C++在運行時不能改變繼承層次結構。編譯並鏈接程序後,程序幾乎就固定了。在Objective-C中,對象只需要方法就可以實現自身的可調用性。這樣,任何對象都可以成為其他對象的數據源和委托。缺少多重繼承可能會給我們帶來諸多不便,但是,我們向任何對象發送任何消息時不必再考慮它的繼承血統,這在很大程度上簡化了我們的工作。
顯然,與C++相比,向任何對象發送任何消息降低了而且因為編譯器可以確保對象能處理對應的方法,所以C++是非常安全的。的類型安全性。如果接受消息的對象不能處理該消息,你將會得到運行時的錯誤。Cocoa中沒有類型安全容器,任何對象都可以放入某個容器中。
Objective-C攜帶了許多關於類的元數據,因此,可以通過反射判斷某個對象是否相應某個消息。含有數據源或委托的對象經常采用這種方法。但是首先要檢查委托是否相應某個消息,這樣可以避免可能出現的運行時錯誤。因此,可以通過類別向其他類中添加方法。
通過元數據,可以輕松操作程序中用到的類。可以確定實例變量,實例變量在對象中的布局,以及類定義方法。甚至刪除可執行對象的調試信息也不刪除Objective-C的元數據。
Objective-C中,可以直接想向nil對象發送消息,而不必檢查發送的消息是否為NULL。
所有的Objective-C的對象都是動態分配地址的。
不存在基於棧的對象,不存在臨時對象的自動創建和銷毀,也不存在臨時對象的自動創建和銷毀,也不存在類型間的自動類型轉換。因此,Objective-C對象比基於棧的C++對象更復雜。這樣使用對象地址作為環境指針是安全的,不必擔心某些棧分配的對象會消失。(比如C++中返回局部自動變量的指針,導致再次使用指針是程序崩潰)。
元數據
任何文件系統中的數據分為數據和元數據。數據是指普通文件中的實際數據,而元數據指用來描述一個文件的特征的系統數據,諸如訪問權限、文件擁有者以及文件數據塊的分布信息(inode...)等等。在集群文件系統中,分布信息包括文件在磁盤上的位置以及磁盤在集群中的位置。用戶需要操作一個文件必須首先得到它的元數據,才能定位到文件的位置並且得到文件的內容或相關屬性。
這個好像是數據庫中的元數據,Objective-C的元數據,還沒有找到具體的解釋。