生活随笔
收集整理的這篇文章主要介紹了
C++学习之普通函数指针与成员函数指针
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
http://blog.csdn.net/lisonglisonglisong/article/details/38353863
函數(shù)指針(function pointer) 是通過指向函數(shù)的指針間接調(diào)用函數(shù)。相信很多人對指向一般函數(shù)的函數(shù)指針使用的比較多,而對指向類成員函數(shù)的函數(shù)指針則比較陌生。我最近也被問到了這方面的問題,心中卻也沒有清晰的答案。故決定去查閱資料,并按照自己的思路寫下這篇學習總結(jié)。
一、普通函數(shù)指針
通常我們所說的函數(shù)指針 指的是指向一般普通函數(shù)的指針。和其他指針一樣,函數(shù)指針指向某種特定類型,所有被同一指針運用的函數(shù)必須具有相同的形參類型和返回類型。
[cpp] ?view plain
?copy int ?(*pf)( int ,? int );??? ??
這里,pf指向的函數(shù)類型是int (int, int) ,即函數(shù)的參數(shù)是兩個int型,返回值也是int型。注:*pf兩端的括號必不可少,如果不寫這對括號,則pf是一個返回值為int指針的函數(shù)。
[cpp] ?view plain
?copy #include<iostream> ?? #include<string> ?? using ? namespace ?std;?? ?? typedef ? int ?(*pFun)( int ,? int );?? ?? ?? int ?add( int ?a,? int ?b){?? ????return ?a+b;?? }?? ?? int ?mns( int ?a,? int ?b){?? ????return ?a-b;?? }?? ?? string?merge(const ?string&?s1,? const ?string&?s2){?? ????return ?s1+s2;?? }?? ?? int ?main()?? {?? ????pFun?pf1?=?add;???? ????cout?<<?(*pf1)(2,3)?<<?endl;???? ????pf1?=?mns;?? ????cout?<<?(*pf1)(8,1)?<<?endl;???? ????string?(*pf2)(const ?string&,? const ?string&)?=?merge;?? ????cout?<<?(*pf2)("hello?" ,? "world" )?<<?endl;?? ?? ????return ?0;?? }??
如示例代碼,直接聲明函數(shù)指針變量顯得冗長而煩瑣,所以我們可以使用typedef 定義自己的函數(shù)指針類型。另外,函數(shù)指針還可以作為函數(shù)的形參類型,實參則可以直接使用函數(shù)名。
二、成員函數(shù)指針
成員函數(shù)指針(member function pointer) 是指可以指向類的非靜態(tài)成員函數(shù)的指針。類的靜態(tài)成員不屬于任何對象,因此無須特殊的指向靜態(tài)成員的指針,指向靜態(tài)成員的指針與普通指針沒有什么區(qū)別。與普通函數(shù)指針不同的是, 成員函數(shù)指針不僅要指定目標函數(shù)的形參列表和返回類型,還必須指出成員函數(shù)所屬的類。因此,我們必須在*之前添加classname:: 以表示當前定義的指針指向classname的成員函數(shù):
[cpp] ?view plain
?copy int ?(A::*pf)( int ,? int );??? ??
同理,這里
A::*pf
兩端的括號也是必不可少的,如果沒有這對括號,則pf是一個返回A類數(shù)據(jù)成員(int型)指針的函數(shù)。注意:和普通函數(shù)指針不同的是,在成員函數(shù)和指向該成員的指針之間不存在自動轉(zhuǎn)換規(guī)則。
[cpp] ?view plain
?copy pf?=?&A::add;??? ?? pf?=?A::add;??????
當我們初始化一個成員函數(shù)指針時,其指向了類的某個成員函數(shù),但并沒有指定該成員所屬的對象——直到使用成員函數(shù)指針時,才提供成員所屬的對象。
下面是一個成員函數(shù)指針的使用示例:
[cpp] ?view plain
?copy class ?A;?? typedef ? int ?(A::*pClassFun)( int ,? int );?? ?? ?? class ?A{?? public :?? ????int ?add( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?+?" ?<<?n?<<? "?=?" ?<<?m+n?<<?endl;?? ????????return ?m+n;?? ????}?? ????int ?mns( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?-?" ?<<?n?<<? "?=?" ?<<?m-n?<<?endl;?? ????????return ?m-n;?? ????}?? ????int ?mul( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?*?" ?<<?n?<<? "?=?" ?<<?m*n?<<?endl;?? ????????return ?m*n;?? ????}?? ????int ?dev( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?/?" ?<<?n?<<? "?=?" ?<<?m/n?<<?endl;?? ????????return ?m/n;?? ????}?? ?? ????int ?call(pClassFun?fun,? int ?m,? int ?n){??? ?? ????????return ?( this ->*fun)(m,?n);?? ????}?? };?? ?? int ?call(A?obj,?pClassFun?fun,? int ?m,? int ?n){??? ?? ????return ?(obj.*fun)(m,?n);?? }?? ?? int ?main()?? {?? ????A?a;?? ????cout?<<?"member?function?'call':" ?<<?endl;?? ????a.call(&A::add,?8,?4);?? ????a.call(&A::mns,?8,?4);?? ????a.call(&A::mul,?8,?4);?? ????a.call(&A::dev,?8,?4);?? ????cout?<<?"external?function?'call':" ?<<?endl;?? ????call(a,?&A::add,?9,?3);?? ????call(a,?&A::mns,?9,?3);?? ????call(a,?&A::mul,?9,?3);?? ????call(a,?&A::dev,?9,?3);?? ????return ?0;?? }??
如示例所示,我們一樣可以使用
typedef
定義成員函數(shù)指針的類型別名。另外,
我們需要留意函數(shù)指針的使用方法
:對于普通函數(shù)指針,是這樣使用
(*pf)(arguments)
,因為要調(diào)用函數(shù),必須先解引用函數(shù)指針,而函數(shù)調(diào)用運算符()的優(yōu)先級較高,所以
(*pf)
的括號必不可少;對于成員函數(shù)指針,唯一的不同是需要在某一對象上調(diào)用函數(shù),所以只需要加上成員訪問符即可:
[cpp] ?view plain
?copy (obj.*pf)(arguments)????????? ?? (objptr->*pf)(arguments)???????
三、函數(shù)表驅(qū)動
對于普通函數(shù)指針和指向成員函數(shù)的指針來說,一種常見的用法就是將其存入一個函數(shù)表(function table) 當中。當程序需要執(zhí)行某個特定的函數(shù)時,就從表中查找對應(yīng)的函數(shù)指針,用該指針來調(diào)用相應(yīng)的程序代碼,這個就是函數(shù)指針在表驅(qū)動法 中的應(yīng)用。
表驅(qū)動法(Table-Driven Approach) 就是用查表的方法獲取信息。通常,在數(shù)據(jù)不多時可用邏輯判斷語句(if…else或switch…case)來獲取信息;但隨著數(shù)據(jù)的增多,邏輯語句會越來越長,此時表驅(qū)動法的優(yōu)勢就體現(xiàn)出來了。
[cpp] ?view plain
?copy #include<iostream> ?? #include<string> ?? #include<map> ?? using ? namespace ?std;?? ?? class ?A;?? typedef ? int ?(A::*pClassFun)( int ,? int );?? ?? class ?A{?? public :?? ????A(){?????? ????????table["+" ]?=?&A::add;?? ????????table["-" ]?=?&A::mns;?? ????????table["*" ]?=?&A::mul;?? ????????table["/" ]?=?&A::dev;?? ????}?? ????int ?add( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?+?" ?<<?n?<<? "?=?" ?<<?m+n?<<?endl;?? ????????return ?m+n;?? ????}?? ????int ?mns( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?-?" ?<<?n?<<? "?=?" ?<<?m-n?<<?endl;?? ????????return ?m-n;?? ????}?? ????int ?mul( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?*?" ?<<?n?<<? "?=?" ?<<?m*n?<<?endl;?? ????????return ?m*n;?? ????}?? ????int ?dev( int ?m,? int ?n){?? ????????cout?<<?m?<<?"?/?" ?<<?n?<<? "?=?" ?<<?m/n?<<?endl;?? ????????return ?m/n;?? ????}?? ?????? ????int ?call(string?s,? int ?m,? int ?n){?? ????????return ?( this ->*table[s])(m,?n);?? ????}?? private :?? ????map<string,?pClassFun>?table;???? };?? ?? ?? int ?main()?? {?? ????A?a;?? ????a.call("+" ,?8,?2);?? ????a.call("-" ,?8,?2);?? ????a.call("*" ,?8,?2);?? ????a.call("/" ,?8,?2);?? ????return ?0;?? }??
上面是一個示例,示例中的“表”通過map來實現(xiàn)(當然也可以使用數(shù)組)。表驅(qū)動法使用時需要注意:一是如何查表,從表中讀取正確的數(shù)據(jù);二是表里存放什么,如數(shù)值或函數(shù)指針。
總結(jié)
以上是生活随笔 為你收集整理的C++学习之普通函数指针与成员函数指针 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。