C++基礎(chǔ)入門(mén)教程(九):函數(shù)指針之回調(diào)
在Java,要實(shí)現(xiàn)某個(gè)時(shí)間調(diào)用某段代碼,是很簡(jiǎn)單的事情,那就是使用接口。
而在C++里,有一個(gè)比較高深的方式,那就是使用函數(shù)指針。
比如Cocos2d-x的定時(shí)器(schedule)、消息訂閱(NotificationCenter)都使用了函數(shù)指針來(lái)完成回調(diào)的功能。
這也是為什么我們總是能把某個(gè)函數(shù)作為參數(shù)傳進(jìn)去,然后在某個(gè)時(shí)刻這個(gè)函數(shù)會(huì)被調(diào)用。
一、函數(shù)的地址
要獲取一個(gè)int變量的地址很簡(jiǎn)單,比如int num; 那么num的地址就是&num。
而獲取函數(shù)的地址更簡(jiǎn)單,函數(shù)的名字就是函數(shù)的地址,如下代碼:
void hello();
int _tmain(int argc, _TCHAR* argv[])
{
auto p = hello;
p();
return 0;
}
void hello()
{
cout << "helloworld";
}
我們定義了一個(gè)hello函數(shù),然后直接把函數(shù)名字賦值給指針p,于是,就可以把p當(dāng)成了hello函數(shù)來(lái)使用了。
這很簡(jiǎn)單吧。
二、聲明函數(shù)指針
獲取函數(shù)的地址很簡(jiǎn)單,但是,如何聲明函數(shù)指針就變得不那么簡(jiǎn)單了。
我們總不能每次都使用auto來(lái)逃避吧?有時(shí)候我們不得不顯式地聲明函數(shù)指針,那么,如何聲明呢?
還記得我們說(shuō)過(guò)的typedef定義類(lèi)型別名嗎?函數(shù)指針的聲明也是一樣的規(guī)則,先聲明一個(gè)函數(shù),如:void hello();
然后把函數(shù)名字換成指針,如:void (*p)();
沒(méi)錯(cuò),就是這么簡(jiǎn)單,void (*p)(); 就是void hello(); 的聲明了。
立刻再來(lái)試試,這個(gè)函數(shù):int getValue(float dt);
它的函數(shù)指針聲明是什么?沒(méi)錯(cuò),就是:int (*p) getValue(float dt);
沒(méi)錯(cuò),就是這么簡(jiǎn)單int getValue(float dt); 就是int (*p) getValue(float dt);的函數(shù)指針聲明了。
立刻再來(lái)試試,這..(小若:停~!別以為我不在你就可以亂來(lái)!)
好吧,那就不繼續(xù)試了,我們來(lái)看看,剛剛那段代碼可以這樣寫(xiě):
void hello();
int _tmain(int argc, _TCHAR* argv[])
{
void (*p)();
p = hello;
p();
(*p)(); // 偷偷加了這句
return 0;
}
void hello()
{
cout << "helloworld";
}
好了,很簡(jiǎn)單,不多說(shuō)了~
另外,有沒(méi)有發(fā)現(xiàn)我偷偷又加了一句代碼?
沒(méi)錯(cuò),用(*p)();的方式也通過(guò)能成功調(diào)用hello函數(shù),這是為什么呢?
三、歷史原因
由于p是指針,它指向的是hello函數(shù)的地址,所以,*p就代表hello函數(shù),于是,(*p)()就等于hello(),這是正常的邏輯。
所以,其實(shí)(*p)()才是比較正常的調(diào)用方式。
然而,由于函數(shù)名本來(lái)就是指向了函數(shù)的指針,也就是說(shuō),hello其實(shí)也是指向了函數(shù)的地址。
換句話說(shuō),p和hello其實(shí)都是指針,那么,p的調(diào)用方式和hello的調(diào)用方式應(yīng)該也是一樣的,于是,p()就相當(dāng)于hello()。
這兩種方式都是正確的,其實(shí)語(yǔ)法這東西,就是人定的,歷史上前輩對(duì)這兩種方式各持所見(jiàn),于是就容忍了這兩種看似沖突的方式同時(shí)存在了。
不過(guò),我想,大部分人都會(huì)更喜歡直接用p(),而不是(*p)()吧。
四、typedef挽救復(fù)雜的函數(shù)指針
如下代碼:
string hehe1(int num, float value);
string hehe2(int num, float value);
string hehe3(int num, float value);
int _tmain(int argc, _TCHAR* argv[])
{
/* 聲明函數(shù)指針數(shù)組 */
string(*p[3])(int num, float value) = {hehe1, hehe2, hehe3};
string result = p[1](1, 2);
cout << result.c_str() << endl;
return 0;
}
string hehe1(int num, float value)
{
return "haha1";
}
string hehe2(int num, float value)
{
return "haha2";
}
string hehe3(int num, float value)
{
return "haha3";
}
這段代碼有三個(gè)參數(shù)和返回值都相同的函數(shù),分別是hehe1、hehe2、hehe3
然后,我們要聲明一個(gè)數(shù)組,這個(gè)數(shù)組用來(lái)存放這三個(gè)函數(shù)指針。
這里的函數(shù)還算是比較簡(jiǎn)單的,所以看起來(lái)不算復(fù)雜。
但如果這樣的聲明出現(xiàn)太多的話,未免會(huì)讓人很沮喪。
于是,typedef挽救了我們,我們可以復(fù)雜的聲明變成這樣:
int _tmain(int argc, _TCHAR* argv[])
{
/* 用HeheFunc來(lái)代替復(fù)雜的函數(shù)聲明 */
typedef string(*HeheFunc)(int num, float value);
/* 聲明函數(shù)指針數(shù)組 */
HeheFunc p[3] = { hehe1, hehe2, hehe3 };
string result = p[1](1, 2);
cout << result.c_str() << endl;
return 0;
}
使用typedef代替函數(shù)聲明之后,我們就能很輕松地使用它,并且會(huì)讓我們的代表變得很簡(jiǎn)單,很好理解。
現(xiàn)在,HeheFunc就代表了一種類(lèi)型,什么類(lèi)型呢?就是參數(shù)為(int num, float value),返回值為string的函數(shù)類(lèi)型。
五、結(jié)束
好了,就嘮叨這么多吧。
上一篇:C++基礎(chǔ)入門(mén)教程(三):數(shù)組、字符串、結(jié)構(gòu)體、共用體
欄 目:C語(yǔ)言
下一篇:MFC設(shè)置對(duì)話框焦點(diǎn)的方法簡(jiǎn)述
本文標(biāo)題:C++基礎(chǔ)入門(mén)教程(九):函數(shù)指針之回調(diào)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3193.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類(lèi)算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?