函數(shù)指針的概念是指向函數(shù)的指針變量。 因而“函數(shù)指針”本身首先應是指針變量,只不過該指針變量指向函數(shù)。在大多數(shù)情況下我們使用不到,也忽略了它的存在。函數(shù)名實際上也是一種指針,指向函數(shù)的入口地址,但它又不同于普通的如int*、double*指針,看下面的例子來理解函數(shù)指針的概念:
view plain int function( int x, int y );int main ( void )
{ int (*fun) ( int x, int y );int a = 10, b = 20;function( a, b );fun = function;(*fun)( a, b );……
}第一行代碼首先定義了一個函數(shù)function,其輸入為兩個整型數(shù),返回也為一個整型數(shù)(輸入參數(shù)和返回值可為其它任何數(shù)據(jù)類型);后面又定義了一個函數(shù)指針fun,與int*或double*定義指針不同的是,函數(shù)指針的定義必須同時指出輸入參數(shù),表明這是一個函數(shù)指針,并且*fun也必須用一對括號括起來;并將函數(shù)指針賦值為函數(shù)function,前提條件是*fun和function的輸入參數(shù)和返回值必須保持一致,否則無法通過編譯。可以直接調用函數(shù)function(),也可以直接調用函數(shù)指針,二者是等效的。
聲明函數(shù)指針
回調函數(shù)是一個程序員不能顯式調用的函數(shù);通過將回調函數(shù)的地址傳給調用者從而實現(xiàn)調用。要實現(xiàn)回調,必須首先定義函數(shù)指針。盡管定義的語法有點不可思議,但如果你熟悉函數(shù)聲明的一般方法,便會發(fā)現(xiàn)函數(shù)指針的聲明與函數(shù)聲明非常類似。請看下面的例子:
void f(); // 函數(shù)原型
上面的語句聲明了一個函數(shù),沒有輸入參數(shù)并返回void.那么函數(shù)指針的聲明方法如下:
void (*) ();
函數(shù)存放在內存的代碼區(qū)域內,它們同樣有地址,我們如何能獲得函數(shù)的地址呢?
如果我們有一個int test(int a)的函數(shù),那么,它的地址就是函數(shù)的名字,這一點如同數(shù)組一樣,數(shù)組的名字就是數(shù)組的起始地址。
定義一個指向函數(shù)的指針用如下的形式,以上面的test()為例:
int (*fp)(int a); //這里就定義了一個指向函數(shù)的指針
函數(shù)指針絕對不能指向不同類型,或者是帶不同形參的函數(shù),在定義函數(shù)指針的時候我們很容易犯如下的錯誤。
int *fp(int a); //這里是錯誤的,因為按照結合性和優(yōu)先級來看就是先和()結合,然后變成了一個返回整形指針的函數(shù)了,而不是函數(shù)指針,這一點尤其需要注意!
例如函數(shù)原型為:
int fun(int *, int);
則函數(shù)指針可以聲明為: int (*pf)(int *, int);
當然從上述例子看不出函數(shù)指針的優(yōu)點,目的主要是想引出函數(shù)指針數(shù)組的概念。我們從上面例子可以得知,既然函數(shù)名可以通過函數(shù)指針加以保存,那們也一定能定義一個數(shù)組保存若干個函數(shù)名,這就是函數(shù)指針數(shù)組。正確使用函數(shù)指針數(shù)組的前提條件是,這若干個需要通過函數(shù)指針數(shù)組保存的函數(shù)必須有相同的輸入、輸出值。
view plain //首先定義256個處理函數(shù)(及其實現(xiàn))。
int function0( int *, int );……
int function255( int *, int );
//其次定義函數(shù)指針數(shù)組,并給數(shù)組賦值。
void (*fun[256])( int *, int );
fun[0] = function0;……
fun[255] = function255;
如果賦了不同的值給函數(shù)指針,那么調用者將調用不同地址的函數(shù)。賦值可以發(fā)生在運行時,這樣使你能實現(xiàn)動態(tài)綁定。
下面我們來看一個具體的例子:
view plain int test(int a)
{ return a;}
int main(void)
{ int (*fp)(int a);fp = test; //將函數(shù)test的地址賦給函數(shù)指針fp cout《fp(5)《“|”《(*fp)(10)《endl; //輸出fp(5),這是標準c++的寫法,(*fp)(10)這是兼容c語言的標準寫法,兩種同意,但注意區(qū)分,避免寫的程序產生移植性問題!
return 0;} typedef定義可以簡化函數(shù)指針的定義,在定義一個的時候感覺不出來,但定義多了就知道方便了,上面的代碼改寫成如下的形式:
view plain int test(int a)
{ return a;}
int main(void)
{ typedef int (*fp)(int a); //注意,這里不是生命函數(shù)指針,而是定義一個函數(shù)指針的類型,這個類型是自己定義的,類型名為fp fp fpi; //這里利用自己定義的類型名fp定義了一個fpi的函數(shù)指針!
fpi = test;cout《fpi(5)《“|”《(*fpi)(10)《endl; //輸出fp(5),這是標準c++的寫法,(*fp)(10)這是兼容c語言的標準寫法,兩種同意,但注意區(qū)分,避免寫的程序產生移植性問題!
return 0;}
view plain int function( int x, int y );int main ( void )
{ int (*fun) ( int x, int y );int a = 10, b = 20;function( a, b );fun = function;(*fun)( a, b );……
}第一行代碼首先定義了一個函數(shù)function,其輸入為兩個整型數(shù),返回也為一個整型數(shù)(輸入參數(shù)和返回值可為其它任何數(shù)據(jù)類型);后面又定義了一個函數(shù)指針fun,與int*或double*定義指針不同的是,函數(shù)指針的定義必須同時指出輸入參數(shù),表明這是一個函數(shù)指針,并且*fun也必須用一對括號括起來;并將函數(shù)指針賦值為函數(shù)function,前提條件是*fun和function的輸入參數(shù)和返回值必須保持一致,否則無法通過編譯。可以直接調用函數(shù)function(),也可以直接調用函數(shù)指針,二者是等效的。
聲明函數(shù)指針
回調函數(shù)是一個程序員不能顯式調用的函數(shù);通過將回調函數(shù)的地址傳給調用者從而實現(xiàn)調用。要實現(xiàn)回調,必須首先定義函數(shù)指針。盡管定義的語法有點不可思議,但如果你熟悉函數(shù)聲明的一般方法,便會發(fā)現(xiàn)函數(shù)指針的聲明與函數(shù)聲明非常類似。請看下面的例子:
void f(); // 函數(shù)原型
上面的語句聲明了一個函數(shù),沒有輸入參數(shù)并返回void.那么函數(shù)指針的聲明方法如下:
void (*) ();
函數(shù)存放在內存的代碼區(qū)域內,它們同樣有地址,我們如何能獲得函數(shù)的地址呢?
如果我們有一個int test(int a)的函數(shù),那么,它的地址就是函數(shù)的名字,這一點如同數(shù)組一樣,數(shù)組的名字就是數(shù)組的起始地址。
定義一個指向函數(shù)的指針用如下的形式,以上面的test()為例:
int (*fp)(int a); //這里就定義了一個指向函數(shù)的指針
函數(shù)指針絕對不能指向不同類型,或者是帶不同形參的函數(shù),在定義函數(shù)指針的時候我們很容易犯如下的錯誤。
int *fp(int a); //這里是錯誤的,因為按照結合性和優(yōu)先級來看就是先和()結合,然后變成了一個返回整形指針的函數(shù)了,而不是函數(shù)指針,這一點尤其需要注意!
例如函數(shù)原型為:
int fun(int *, int);
則函數(shù)指針可以聲明為: int (*pf)(int *, int);
當然從上述例子看不出函數(shù)指針的優(yōu)點,目的主要是想引出函數(shù)指針數(shù)組的概念。我們從上面例子可以得知,既然函數(shù)名可以通過函數(shù)指針加以保存,那們也一定能定義一個數(shù)組保存若干個函數(shù)名,這就是函數(shù)指針數(shù)組。正確使用函數(shù)指針數(shù)組的前提條件是,這若干個需要通過函數(shù)指針數(shù)組保存的函數(shù)必須有相同的輸入、輸出值。
view plain //首先定義256個處理函數(shù)(及其實現(xiàn))。
int function0( int *, int );……
int function255( int *, int );
//其次定義函數(shù)指針數(shù)組,并給數(shù)組賦值。
void (*fun[256])( int *, int );
fun[0] = function0;……
fun[255] = function255;
如果賦了不同的值給函數(shù)指針,那么調用者將調用不同地址的函數(shù)。賦值可以發(fā)生在運行時,這樣使你能實現(xiàn)動態(tài)綁定。
下面我們來看一個具體的例子:
view plain int test(int a)
{ return a;}
int main(void)
{ int (*fp)(int a);fp = test; //將函數(shù)test的地址賦給函數(shù)指針fp cout《fp(5)《“|”《(*fp)(10)《endl; //輸出fp(5),這是標準c++的寫法,(*fp)(10)這是兼容c語言的標準寫法,兩種同意,但注意區(qū)分,避免寫的程序產生移植性問題!
return 0;} typedef定義可以簡化函數(shù)指針的定義,在定義一個的時候感覺不出來,但定義多了就知道方便了,上面的代碼改寫成如下的形式:
view plain int test(int a)
{ return a;}
int main(void)
{ typedef int (*fp)(int a); //注意,這里不是生命函數(shù)指針,而是定義一個函數(shù)指針的類型,這個類型是自己定義的,類型名為fp fp fpi; //這里利用自己定義的類型名fp定義了一個fpi的函數(shù)指針!
fpi = test;cout《fpi(5)《“|”《(*fpi)(10)《endl; //輸出fp(5),這是標準c++的寫法,(*fp)(10)這是兼容c語言的標準寫法,兩種同意,但注意區(qū)分,避免寫的程序產生移植性問題!
return 0;}