2011-05-26 30 views
3

我在想如何看待Objective C動態消息系統的典型(或至少Apple)實現。在編譯和運行時如何處理選擇器,NSObject*真的指向什麼,在那裏如何找到方法實現。典型的目標C消息實現

在C++中,我們有虛擬函數;它們如何實現正式是一個實現細節,但實際上,作爲第一個數據成員的VF表指針實際上是給定的。我想知道是否有類似的無處不在的方式來實現ObjC的類系統。

+3

bbum's [objc_msgSend()Tour](http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/)是一個很棒的閱讀。 – 2011-05-26 04:29:03

+0

@Bavarious:請讓這個答案。一旦我讀到最後,我會接受。 – 2011-05-26 12:28:12

回答

3

查看最近的開發Mac上/usr/include/objc的標題,瞭解一些底層對象的詳細信息。 (Apple在新的運行時改變了一些東西,但是許多改變還沒有被髮布,關於原始實現的細節可以在這些頭文件中找到,或者通過使用「objective c runtime」搜索。)一些亮點:一個對象是隻是一個包含實例變量的結構。該結構中的第一個元素稱爲isa,它只是指向類對象(或類對象的超類)的指針。類對象包含指定類中不同方法和變量的名稱和位置的數據,並且運行時在查找方法時引用這些數據結構。第一次查找方法後,將其存儲在表格中供將來參考。

+0

我的理解是,對於10.5中的實例變量,有一個額外的間接級別來完全消除脆弱的基類問題,因此他們現在可以動態地添加到某個程度上? – Tommy 2011-05-26 12:44:33

+0

@Tommy你是對的。當使用現代運行時(x86_64,iOS)時,編譯器發出在訪問伊娃時使用變量(運行時)伊維爾偏移的代碼,而對傳統結構成員的訪問則是通過在編譯時計算和修正的偏移來完成的。 – 2011-05-26 14:35:06

+0

@Tommy是的,這就是爲什麼我說你會主要找到有關原始運行時的細節。然而,結構開始處的類指針仍然是相同的(它是'id'的定義的一部分),我相信類對象使用類似的結構,儘管蘋果並沒有將它聲明爲這樣,而是提供了抽象屏障功能。 – ughoavgfhw 2011-05-26 18:10:14

1

Apple官方Objective-C Runtime Reference記錄了提供Objective-C所有調度,反射和其他面向對象任務的C庫。大多數實際使用的數據結構都是不透明的 - 我認爲它們都是從10.5開始的 - 並且沒有任何理由假設在1986年實現一條連續的線。

編譯器只是將您的Objective-C東西轉換爲調用運行時間;你也可以自己調用它來獲取諸如C函數指針的東西給你的方法,然後你可以在沒有正常開銷的情況下調度它,儘管代價是一大堆其他機制不再有效。