亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

從C/C++語言到Objective-C語言

系統 2653 0

無標題文檔

原文鏈接: http://www.yifeiyang.net/iphone-development-introduction-7-from-the-c-c-language-to-objective-c-language/

Objective-C,通常寫作ObjC和較少用的Objective C或Obj-C,是擴充C的面向對象編程語言。所以有一定C/C++語言基礎理解和掌握Objective-C也會相應的快些。這回,我們將比較著學習 Objective-C語言,掌握其語法并理解其思想。

語法

讓我們先來看看C++和Objective-C中對于類的宣言 :

C++
從C/C++語言到Objective-C語言

Objective-C
從C/C++語言到Objective-C語言

通過比較上面兩段代碼,從語法的角度上我們看到 Objective-C 語言有以下特點:

  • 用 #import 取代了 #include

#import 相當于 C/C++ 語言中的 #include+#pragma once。當頭文件嵌套包含的時候,它的作用就發揮出來了。
當某一頭文件已經被讀取后,又一次被 #include 的時候,#pragma once 這會跳過該次讀取。
比如我們在C/C++語言的頭文件中常常這樣定義,就是為了實現 #pragma once 而做的 :


  • 繼承的時候沒有限定符
    繼承都是 public 的。
  • 沒有構建和虛構函數
  • 成員變量/函數沒有限定符
    成員變量缺省是 private 的,而函數是 public 的。
  • 沒有const關鍵字
  • 沒有virtual關鍵字
    Objec tive-C 中函數缺省的就是 virtual 的。

接下來再看看具體的實現 :

C++
從C/C++語言到Objective-C語言
Objective-C

從C/C++語言到Objective-C語言

  • 實例方法

方法前面的“-”是實例方法(類似于C++中的類成員函數)

  • 類方法

前綴為“+”的是類方法(類似于C++中的靜態成員函數,或者是全局函數)

  • 類變量

與C/C++語言中的靜態變量一樣,Objective-C 中的類變量就是以 static 聲明的變量。(只在當前定義文件中有效)
如果子類也想參照父類中的類變量的時候,須定義屬性參照方法(類方法)。(這與面向對象中的封裝概念有所背馳,降低了 凝聚度

  • 單一繼承

Objective-C 與 Java 語言一樣,都是單一繼承。 如果想實現多重繼承,可以只用類似Java 中 implements 的方法。(Objective-C 中叫做 protocol)

  • 發送消息

Objective-C 中類似于C/C++中函數調用的地方都被稱作“ 發送消息 ”。調用某個函數,被稱為發送了某個消息。其形式如下圖所示 :
從C/C++語言到Objective-C語言

Objective-C的發送消息

  • 方法,SEL,方法實現

Objective-C 中方法,SEL型,實現的關系如如下圖所示 :
從C/C++語言到Objective-C語言
Objective-C的方法

概念

SEL,IMP的定義

接下來,我們來看看 Objective-C 語言中的頭文件 objc.h 的定義 :
從C/C++語言到Objective-C語言

id
id和void *并非完全一樣。 在上面的代碼中,id是指向struct objc_object的一個指針,這個意思基本上是說,id是一個指向任何一個繼承了Object(或者NSObject)類的對象。 需要注意的是id 是一個指針,所以你在使用id的時候不需要加星號。 比如id foo=nil定義了一個nil指針,這個指針指向NSObject的一個任意子類。而id *foo=nil則定義了一個指針,這個指針指向另一個指針,被指向的這個指針指向NSObject的一個子類。
從C/C++語言到Objective-C語言
nil
nil和C語言的NULL相同,在objc/objc.h中定義。 nil表示一個Objctive-C對象,這個對象的 指針指向空 (沒有東西就是空)。
Nil
首字母大寫的Nil和nil有一點不一樣, Nil定義一個 指向空的類 (是Class,而不是對象)。
SEL
SEL是“selector”的一個類型,表示一個方法的名字。比如以下方法:

-[Foo count] 和 -[Bar count] 使用同一個selector,它們的selector叫做count。

在上面的頭文件里我們看到, SEL是指向 struct objc_selector的指針, 但是objc_selector是什么呢?那么實際上,你使用GNU Objective-C的運行時間庫和NeXT Objective-C的運行運行時間庫(Mac OS X使用NeXT的運行時間庫)時,它們的定義是不一樣的。實際上Mac OSX僅僅將SEL映射為C字符串。比如,我們定義一個Foo的類,這個類帶有一個- (int) blah方法,那么以下代碼:

會輸出為 SEL=blah。 說白了SEL就是 返回方法名

這樣的機制大大的增加了我們的程序的靈活性,我們可以通過給一個方法傳遞SEL參數,讓這個方法動態的執行某一個方法;我們也可以通過配置文件指定需要執行的方法,程序讀取配置文件之后把方法的字符串翻譯成為SEL變量然后給相應的對象發送這個消息。

在 Objective-C 運行時庫中,selector 是作為數組來管理的。這都是從效率的角度出發:函數調用的時候,不是通過方法名字比較而是指針值的比較來查找方法,由于整數的查找和匹配比字符串要快得多,所以這樣可以在某種程度上提高執行的效率。

這樣就必須保證所有類中的 selector 須指向同一實體(數組)。一旦有新的類被定義,其中的 selector 也需要映射到這個數組中。

實際情況下,總共有兩種 selector 的數組: 預先定義好的 內置selector數組 用于 動態追加的selector數組

  • 內置selector

簡單地說,內置的selector就是一個大的字符串數組。定義在objc-sel-table.h文件中:
從C/C++語言到Objective-C語言
可以看到,數組的大小NUM_BUILTIN_SELS定義為 16371 。字符串按照字母順序排序,簡單的都是為了運行時檢索的速度( 二分法查找 )。 從定義好的 selector 名稱我們可以看到一些新的方法名稱,比如 CIConetext,CI開頭的方法是由Tiger開始導入的程序庫。
每次系統更新的時候,這個數組也是需要更新的。

  • 動態追加selector

另一個用于動態追加的 selector,其定義在 objc-sel.m 和 objc-sel-set.m 文件中 新的 selector 都被追加到 _buckets 成員中,其中追加和搜索 使用 Hash 算法
從C/C++語言到Objective-C語言

IMP

從上面的頭文件中我們可以看到,IMP定義為

這樣說來, IMP是一個 指向函數的指針 ,這個被指向的函數包括id(“self”指針),調用的SEL(方法名),再加上一些其他參數。說白了IMP就是 實現方法

我們取得了函數指針之后, 也就意味著我們取得了執行的時候的這段方法的代碼的 入口 ,這樣我們就可以像普通的C語言函數調用一樣使用這個函數指針。 當 然我們可以把函數指針作為參數傳遞到其他的方法,或者實例變量里面,從而獲得極大的動態性。我們獲得了動態性,但是付出的代價就是編譯器不知道我們要執行 哪一個方法所以在編譯的時候不會替我們找出錯誤,我們只有執行的時候才知道,我們寫的函數指針是否是正確的。所以,在使用函數指針的時候要非常準確地把握 能夠出現的所有可能,并且做出預防。尤其是當你在寫一個供他人調用的接口API的時候,這一點非常重要。

方法的定義

在頭文件 objc-class.h 中,有方法的定義 :

從C/C++語言到Objective-C語言

這個定義看上去包括了我們上面說過的其他類型。也就是說,Method(我們常說的方法)表示一種類型,這種類型與selector和實現(implementation)相關。

最初的SEL是方法的名稱method_name。char型的method_types表示方法的參數。最后的IMP就是實際的函數指針,指向函數的實現。

Class的定義

Class(類)被定義為一個指向struct objc_class的指針,在objc/objc-class.h中它是這么定義的:
從C/C++語言到Objective-C語言

由以上的結構信息,我們可以像類似于C語言中結構體操作一樣來使用成員。比如下面取得類的名稱:

發送消息與函數調用的不同

Objective-C的消息傳送如下圖所示 :

從C/C++語言到Objective-C語言

發送消息的過程,可以總結為以下內容 :

  • 首先,指定調用的方法
  • 為了方法調用,取得 selector

源代碼被編譯以后,方法被解釋為 selector。這里的 selector 只是單純的字符串。

  • 消息發送給對象B

消息傳送使用到了 objc_msgSend 運行時API。這個API只是將 selector 傳遞給目標對象B。

  • 從 selector 取得實際的方法實現

首先,從對象B取得類的信息,查詢方法的實現是否被緩存(上面類定義中的struct objc_cache *cache;)。如果沒有被緩 存,則在方法鏈表中查詢(上面類定義中的struct objc_method_list **methodLists;)。

  • 執行

利用函數指針,調用方法的實現。這時,第一個參數是對象實例,第二個是 selector。

  • 傳送返回值

利用 objc_msgSend API 經方法的返回值傳送回去。

簡單地從上面發送消息的過程可以看到,最終還是以函數指針的方式調用了函數。為什么特意花那么大的功夫繞個大圈子呢?

這些年,隨著程序庫尺寸的擴大,動態鏈接庫的使用已經非常普遍。就是說,應用程序本身并不包括庫代碼,而是在啟動時或者運行過程中動態加載程序庫。這樣一來一方面可以減小程序大小,另一方面可以提升了代碼重用(不用再造輪子)。但是,隨之帶來了向下兼容的問題。

如果程序庫反復升級,添加新的方法的時候,開發者與用戶間必須保持一致的版本,否則將產生運行時錯誤。一般,解決這個問題是,調用新定義的方法的時 候,實現檢查當前系統中是否存在新方法的實現。如果沒有,跳過它或者簡單地產生警告信息。 Objective-C中的respondsToSelector:方法就可以用來實現這樣的動作。

但是,這并不是萬全的解決方案。如果應用程序與新的動態程序庫(含有新定義的API)一起編譯后,新定義的API符號也被包含進去。而這樣的應用程 序放到比較舊的系統(舊的動態程序庫)中運行的時候,因為找不到鏈接符號,程序將不能啟動。這就是 win32系統中常見的「DLL地域」。

為了解決這個問題, Objective-C 編譯得到的二進制文件中,函數是作為 selector 來保存的 。就是說,不管調用什么函數,二進制文件中不會包含符號信息。為了驗證 Objective-C 編譯的二進制文件是否包含符號信息,這里用 nm 命令來查看。

源代碼如下 :
從C/C++語言到Objective-C語言
這里調用了 alloc、initWithString:、length 等方法。

從C/C++語言到Objective-C語言

可以看到,這里沒有alloc、initWithString:、length3個方法的符號。所以,即使我們添加了新的方法,也可以在任何新舊系 統中運行。當然,函數調用之前,需要使用 respondsToSelector: 來確定方法是否存在。正是這樣的特性,使得程序可以運行時動態地查詢要執行的方法,提高了 Objective-C 語言的柔韌性。

Target-Action Paradigm

Objective-C 語言中,GUI控件對象間的通信利用 Target-Action Paradigm。不像其他事件驅動的 GUI 系統實現的那樣,需要以回調函數的形式注冊消息處理函數(Win32/MFC,Java AWT, X Window)。Target-Action Paradigm 完全是面向對象的事件傳遞機制。

例如用戶點擊菜單的事件,用Target-Action Paradigm來解釋就是,調用菜單中被設定目標的Action。這個Action對應的方法不一定需要實現。目標與Action的指定與方法的實現沒 有關系,源代碼編譯的時候不會檢測,只是在運行時確認(參考前面消息傳送的機制)。

運行時,通過 respondsToSelector: 方法來檢查實現的情況。如果有實現,那么使用 performSelector:withObject: 來調用具體的Action,像是下面的代碼:
從C/C++語言到Objective-C語言
通過這樣的架構,利用 setTarget: 可以更該其他的目標,或者 setAction: 變換不同的Action。實現動態的方法調用。

從C/C++語言到Objective-C語言


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美日韩国产成人综合在线影院 | a级毛片高清免费视频 | 四虎影永久地址www 四虎影永久在线高清免费 四虎影永久在线观看精品 四虎影永久在线观看网址 四虎影院.com | 四虎最新免费观看网址 | 国产不卡影院 | 中文字幕一区二区在线观看 | 免费视频成人国产精品网站 | 国产一区二区在线观看免费 | 欧美日韩一二三区免费视频观看 | 一级录像 | 国产香蕉精品视频在 | 800玖玖爱在线观看香蕉 | 性做久久久久久久久25的美女 | 奇米影视第七色 | 欧美成人久久 | 男女污污在线观看 | 亚洲在线欧美 | 性夜影院爽黄a爽免费看网站 | 久久国产精品久久国产精品 | 亚洲精品98久久久久久中文字幕 | 亚洲精品宾馆在线精品酒店 | se94se欧美综合色 | 天天做天天操 | 小香蕉影院 | 中文精品99久久国产 | 国产精品小视频在线观看 | 国产成人h综合亚洲欧美在线 | 香蕉成人在线 | 91精品啪国产在线观看免费牛牛 | 国产成人18黄禁网站免费观看 | 欧美日韩国产在线人成 | 国产在线98福利播放视频免费 | 精品国产一区二区三区久久 | 中国jizz18免费 | 久久婷婷综合中文字幕 | 久久99国产这里有精品视 | 国产在线精品一区二区高清不卡 | 香蕉久久夜色精品国产2020 | 久久精品国产波多野结衣 | 一级毛片老太婆交性欧美 | 国产成人综合网在线观看 |