C++函數指針
一 函數指針介紹
函數指針指向某種特定類型,函數的類型由其參數及傳回類型共同決定,與函數名無關。舉例如下:
int add(int nLeft,int nRight);//函數定義
該函數類型為int(int,int),要想聲明一個指向該類函數的指針,隻需用指針替換函數名即可:
int (*pf)(int,int);//未初始化
則pf可指向int(int,int)類型的函數。pf前面有*,說明pf是指針,右側是形參清單,表示pf指向的是函數,左側為int,說明pf指向的函數傳回值為int。則pf可指向int(int,int)類型的函數。而add類型為int(int,int),則pf可指向add函數。
pf = add;//通過指派使得函數指針指向某具體函數
注意:*pf兩端的括号必不可少,否則若為如下定義:
int *pf(int,int);//此時pf是一個傳回值為int*的函數,而非函數指針
二 标準C函數指針
1函數指針的定義
1.1 普通函數指針定義
int (*pf)(int,int);
1.2 使用typedef定義函數指針類型
typedef int (*PF)(int,int);
PF pf;//此時,為指向某種類型函數的函數指針類型,而不是具體指針,用它可定義具體指針</span>
2函數指針的普通使用
pf = add;
pf(100,100);//與其指向的函數用法無異
(*pf)(100,100);//此處*pf兩端括号必不可少
注意:add類型必須與pf可指向的函數類型完全比對
3函數指針作為形參
//第二個形參為函數類型,會自動轉換為指向此類函數的指針
Void fuc(int nValue,int pf(int,int));
//等價的聲明,顯示的将形參定義為指向函數的指針
Void fuc(int nValue,int (*pf)(int,int));
Void fuc(int nValue,PF);
形參中有函數指針的 函數調用,以fuc為例:
pf = add;//pf是函數指針
fuc(1,add);//add自動轉換為函數指針
fuc(1,pf);
4傳回指向函數的指針
4.1 使用typedef定義的函數指針類型作為傳回參數
PF fuc2(int);//PF為函數指針類型
4.2 直接定義函數指針作為傳回參數
int (*fuc2(int))(int,int);//顯示定義
說明:按照有内向外的順序閱讀此聲明語句。fuc2有形參清單,則fuc2是一個函數,其形參為fuc2(int),fuc2前面有*,是以fuc2傳回一個指針,指針本身也包含形參清單(int,int),是以指針指向函數,該函數的傳回值為int.
總結:fuc2是一個函數,形參為(int),傳回一個指向int(int,int)的函數指針。
二 C++函數指針
1由于C++完全相容C,則C中可用的函數指針用法皆可用于C++
2 C++其他函數(指針)定義方式及使用
2.1 typedef與decltype組合定義函數類型
typedef decltype(add) add2;
decltype傳回函數類型,add2是與add相同類型的函數,不同的是add2是類型,而非具體函數。
使用方法:
add2* pf;//pf指向add類型的函數指針,未初始化
2.2 typedef與decltype組合定義函數指針類型
typedef decltype(add)* PF2;//PF2與1.1PF意義相同
PF2 pf;// pf指向int(int,int)類型的函數指針,未初始化
2.3 使用推斷類型關鍵字auto定義函數類型和函數指針
auto pf = add;//pf可認為是add的别名(個人了解)
auto *pf = add;//pf為指向add的指針
3函數指針形參
typedef decltype(add) add2;
typedef decltype(add)* PF2;
void fuc2 (add2 add);//函數類型形參,調用自動轉換為函數指針
void fuc2 (PF2 add);//函數指針類型形參,傳入對應函數(指針)即可
說明:不論形參聲明的是函數類型:void fuc2 (add2 add);還是函數指針類型void fuc2 (PF2 add);都可作為函數指針形參聲明,在參數傳入時,若傳入函數名,則将其自動轉換為函數指針。
4 傳回指向函數的指針
4.2 使用auto關鍵字
auto fuc2(int)-> int(*)(int,int) //fuc2傳回函數指針為int(*)(int,int)
4.2 使用decltype關鍵字
decltype(add)* fuc2(int)//明确知道傳回哪個函數,可用decltype關鍵字推斷其函數類型,
5 成員函數指針
5.1普通成員函數指針使用舉例
class A//定義類A
{
private:
int add(int nLeft, int nRight)
{
return (nLeft + nRight);
}
public:
void fuc()
{
printf("Hello world\n");
}
};
typedef void(A::*PF1)();//指針名前需加上類名限定
PF1 pf1 = &A::fuc; //必須有&
A a;//成員函數位址解引用必須附駐與某個對象位址,是以必須建立一個隊形
(a.*pf1)();//使用成員函數指針調用函數
5.2繼承中的函數指針使用舉例
class A
{
public:
void fuc()
{
printf("Hello fuc()\n");
}
void fuc2()
{
printf("Hello A::fuc2()\n");
}
};
class B:public A
{
public:
virtual void fuc2()
{
printf("Hello B::fuc2()\n");
}
};
typedef void(A::*PF1)();
typedef void(B::*PF2)();
PF1 pf1 = &A::fuc;
int main()
{
A a;
B b;
(a.*pf1)(); //調用A::fuc
(b.*pf1)(); //調用A::fuc
pf1 = &A::fuc2;
(a.*pf1)(); //調用A::fuc2
(b.*pf1)(); //調用A::fuc2
PF2 pf2 = &A::fuc2;
(b.*pf2)(); //調用A::fuc2
}
6重載函數的指針
6.1 重載函數fuc
Void fuc();
Void fuc(int);
6.2 重載函數的函數指針
void (*PF)(int) = fuc;//PF指向fuc(int)
int(*pf2)(int) = fuc;//錯誤沒有比對的類型
注意:編譯器通過指針類型決定選取那個函數,指針類型必須與重載函數中的一個精确比對。