C++函數(shù)指針和Swift的函數(shù)對(duì)象

C++函數(shù)指針和Swift的函數(shù)對(duì)象

在C++中學(xué)習(xí)函數(shù)指針式非常痛苦的事情,而在Swift里面學(xué)習(xí)函數(shù)指針則是非常愉快的京髓。

基本語法

一個(gè)函數(shù)的聲明由函數(shù)名弯汰,參數(shù)列表综慎,返回值三個(gè)部分組成莱找,在實(shí)際應(yīng)用中酬姆,函數(shù)本身也可以當(dāng)作參數(shù),這個(gè)時(shí)候就是函數(shù)指針奥溺,函數(shù)指針賦予C語言一定的動(dòng)態(tài)能力辞色,C++的很多的功能都是通過函數(shù)指針來實(shí)現(xiàn)的,不可謂不重要浮定,在Swift等函數(shù)式編程語言中相满,函數(shù)更是一等公民,下面是一些簡(jiǎn)單的例子

typedef int (*OPERATOR)(int, int);//使用typedef簡(jiǎn)化定義桦卒,使代碼更易懂
OPERATOR op = max;//不使用typedef的話立美,可以直接int (*op)(int, int) = max
                  //c++11之后可以auto op = max
op(10,23);
let op: (Int, Int) -> Int = max

上面C++和Swift定義中op是函數(shù)指針的名稱,指向具體的函數(shù)為max方灾,參數(shù)是兩個(gè)Int建蹄,返回值也是Int,看起來非常簡(jiǎn)單吧裕偿。

類中的函數(shù)指針

請(qǐng)解釋一下這段代碼:int* (Class::*value[2])(int (*)())洞慎,這個(gè)value是什么鬼?

C++中的函數(shù)指針需要考慮作用域嘿棘,比如類成員函數(shù)劲腿,類靜態(tài)成員函數(shù),C++的成員函數(shù)指針和類本身綁定鸟妙,類型非常復(fù)雜焦人,下面代碼中fpr的類型為Number (Number::*)(Number),相比普通的函數(shù)指針多了一個(gè)作用域

class Number {
    int x;
public:
    Number(int value) {
        x = value;
    }
    Number add(Number a){
        return x + a.x;
    }
};
Number (Number::*fpr)(Number) = &Number::add;//復(fù)雜的類型
//auto fpr = &Number::add;//c++11
Number num1(10);
(num1.*fpr)(20);//成員函數(shù)指針的使用方法

在Swift中函數(shù)指針的類型就比較簡(jiǎn)單圆仔,Swift中函數(shù)和閉包區(qū)別不大垃瞧,都可以使用同樣的類型來表示。

class Number {
    var x:Int
    init(_ v:Int) {
        x = v
    }
    func add(_ b:Number) -> Number {
        return Number(x + b.x)
    }
}
var fpr = Number.add
//fpr的類型是 (Number) -> (Number) -> Number坪郭,其中第一個(gè)(Number)就是self指針
let num1 = Number(10)
let num2 = Number(20)
let num3 = fpr(num1)(num2)//num1相當(dāng)于self

在Swift中个从,所有的函數(shù)指針都是一樣的,并不區(qū)分普通函數(shù)指針和成員函數(shù)指針歪沃,同時(shí)嗦锐,你也沒辦法在調(diào)用的時(shí)候感知到這是一個(gè)對(duì)象成員函數(shù)的調(diào)用。

構(gòu)造函數(shù)和析構(gòu)函數(shù)

C++標(biāo)準(zhǔn)規(guī)定不能對(duì)構(gòu)造函數(shù)和析構(gòu)函數(shù)取地址沪曙,另外我們也知道這兩種函數(shù)沒有返回值奕污,也沒辦法定義類型,只能是作為特殊函數(shù)對(duì)待液走,網(wǎng)上也有一些hack的方法碳默,通過匯編取這兩種函數(shù)的地址贾陷,和我們討論的函數(shù)指針關(guān)系不大,這里就不多討論了嘱根。

在C++里面如果需要構(gòu)造函數(shù)的函數(shù)指針髓废,一般會(huì)定義一個(gè)靜態(tài)成員函數(shù)返回一個(gè)對(duì)象來完成,比如Number Number::Create(int value)這樣的该抒,這樣的函數(shù)指針也常常出現(xiàn)在工廠方法里面替代直接調(diào)用構(gòu)造函數(shù)慌洪。

Swift里面構(gòu)造函數(shù)相比其他函數(shù)沒有什么特殊的地方,記住兩步構(gòu)造和安全檢查就差不多了凑保,畢竟創(chuàng)造是比較復(fù)雜的事情冈爹,所以這里可以直接取構(gòu)造函數(shù)的指針,比如Number.init就是一個(gè)類型為(int) -> Number的函數(shù)指針欧引,不過Swift的析構(gòu)函數(shù)因?yàn)椴荒苤苯诱{(diào)用频伤,所以也不能取地址。

上下文

在C++中函數(shù)指針是單純的不帶上下文的维咸,在Swift里面不太一樣剂买,比如說,在Swift語言中可以對(duì)對(duì)象的某個(gè)函數(shù)取指針癌蓖,接著上面的代碼:

var fpr1 = num1.add
let num4 = fpr1(num2)

這里的fpr1的上下文中就包含了num1瞬哼,好比是在閉包捕獲了這個(gè)對(duì)象,調(diào)用fpr1和num1.add是等價(jià)的租副,根據(jù)這個(gè)特性坐慰,可以簡(jiǎn)化很多操作,假如我們有一個(gè)int數(shù)組用僧,需要轉(zhuǎn)換成Number數(shù)組结胀,用map就可以了,代碼是這樣的:

let arr2 = arr1.map(Number.init)
//或者
let arr2 = arr1.map {Number($0)}`

然后我們要給所有的元素都加上num2這個(gè)對(duì)象责循,這里明顯的一點(diǎn)是num1.add(num2)和num2.add(num1)是沒有區(qū)別的糟港,滿足交換律的,所以這個(gè)動(dòng)作可以這么實(shí)現(xiàn):

arr2.map(num2.add)
//或者
arr2.map {$0.add(num2)}

是不是也可以認(rèn)為num1.add是函數(shù)(Number) -> (Number) -> Number的curry院仿,num1是第一個(gè)參數(shù)秸抚,結(jié)果是(Number) -> Number.

重載

overload是現(xiàn)代語言中很重要的一個(gè)特性,可以給同一個(gè)函數(shù)名聲明不同的參數(shù)歹垫,C++中要求參數(shù)的個(gè)數(shù)或類型必須有差異阴挣,而Swift中允許相同的參數(shù)列表和不同的返回值臼寄,根據(jù)返回值推斷具體的函數(shù)調(diào)用棉圈。前面C++代碼里面又一個(gè)C++11之后的特性幌氮,就是auto類型,編譯器自動(dòng)給你生成類型暮芭,免得再去面對(duì)鬼一樣的函數(shù)指針聲明鹿驼,不過這個(gè)也不是萬能的欲低,一旦遇到重載酒不能工作了,還有就是使用函數(shù)指針作參數(shù)的時(shí)候蠢沿,肯定還是要一絲不茍的把聲明給寫出來伸头。那么Swift怎么辦呢匾效?默認(rèn)情況下我們使用let和var的聲明變量的時(shí)候可以不指定類型舷蟀,交給編譯器來推斷,在這種無法推斷的地方面哼,編譯器也無能為力野宜,這里可以使用明確的類型聲明來避免二義性,代碼:

func magicNumber() -> Int {return 2017}
func magicNumber() -> Float {return 2.20}
let f: () -> Float = magicNumber
f()//順利得到2.20

總結(jié)

Swift在設(shè)計(jì)的時(shí)候有很多函數(shù)式編程語言的思想魔策,充分的利用這個(gè)特性會(huì)讓我們的編碼效率更高匈子。

C++的函數(shù)指針相對(duì)比較復(fù)雜,而且經(jīng)常和數(shù)組指針等一起混用變得可讀性比較差闯袒,需要我們?nèi)ゲ鸱执a虎敦。

int* (Class::*value[2])(int (*)())這個(gè)搞明白了嗎?

typedef Paratype = int (*)();
typedef int* (Class::*Cptr)(ParaType);
Cptr value[2];//這就是你要的value政敢,原來是一個(gè)數(shù)組
              //數(shù)組元素類型是Class類的成員函數(shù)指針
              //函數(shù)指針的返回值是int*
              //函數(shù)的參數(shù)類型是Paratype也是一個(gè)函數(shù)指針其徙,是沒有參數(shù)返回int的函數(shù)指針

就這樣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喷户,一起剝皮案震驚了整個(gè)濱河市唾那,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌褪尝,老刑警劉巖闹获,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異河哑,居然都是意外死亡避诽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門璃谨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沙庐,“玉大人,你說我怎么就攤上這事睬罗」旃Γ” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵容达,是天一觀的道長(zhǎng)古涧。 經(jīng)常有香客問我,道長(zhǎng)花盐,這世上最難降的妖魔是什么羡滑? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任菇爪,我火速辦了婚禮,結(jié)果婚禮上柒昏,老公的妹妹穿的比我還像新娘凳宙。我一直安慰自己,他們只是感情好职祷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布氏涩。 她就那樣靜靜地躺著,像睡著了一般有梆。 火紅的嫁衣襯著肌膚如雪是尖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天泥耀,我揣著相機(jī)與錄音饺汹,去河邊找鬼。 笑死痰催,一個(gè)胖子當(dāng)著我的面吹牛兜辞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播夸溶,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼逸吵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蜘醋?” 一聲冷哼從身側(cè)響起胁塞,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎压语,沒想到半個(gè)月后啸罢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胎食,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年扰才,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厕怜。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衩匣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出粥航,到底是詐尸還是另有隱情琅捏,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布递雀,位于F島的核電站柄延,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缀程。R本人自食惡果不足惜搜吧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一市俊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滤奈,春花似錦摆昧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至搞糕,卻和暖如春勇吊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窍仰。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留礼殊,地道東北人驹吮。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像晶伦,于是被迫代替她去往敵國和親碟狞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容