函式指標的作用 (轉載)
我們先來看一下以下 的宣告:
int f(int);
int (*pf)(int)=&f;//&操作符可選;因為函式名被使用時總是由編譯器把它
轉換為函式指標;
int ans;
ans=f(25);
ans=(*pf)(25);
ans=pf(25);//間接訪問操作並非必需,因為編譯器需要的是一個函式指標;
*****************************************************************
兩個最常見的用途是把函式指標作為引數傳遞給函式以及用於轉換表!
1.回撥函式
這裡有一個簡單的函式,它用於在一個單鏈表中查詢一個值,它的引數是一個指向
連結串列第一個節點的指標以及那個需要查詢的值.
Node* search_list(Node* node,int const value)
{ while(node!=NULL)
{ if(node->value==value)
break;
node=node->link;
}
return node;
}
這個函式看上去相當簡單,但它只適用於值為整數的連結串列,如果你需要在一個
字串連結串列中查詢,你不得不另外編寫一個函式,這個函式和上面那個函式的絕大
部分程式碼相同,只是第二個引數的型別以及節點值的比較方法不同.
一種更為通用的方法是查詢函式與型別無關,這樣它就能用於任何型別的值
的連結串列,我們必須對函式的兩個方面進行修改,使它與型別無關.首先我們必須改變
比較的執行方式,這樣函式就可以對任何型別的值進行比較.這個目標聽上去好象
不可能,如果你編寫語句用於比較整型值,它怎麼還可能用於其他型別如字串
的比較呢?解決方案就是使用函式指標,呼叫者編寫一個函式,用於比較兩個值,然後
把一個指向這個函式的指標作為引數傳遞給查詢函式.然後查詢函式呼叫這
個函式來執行值的比較,使用這種方法,任何型別的值都可以進行比較.
我們必須修改的第二個方面是向函式傳遞一個指向值的指標而不是本身.
函式由一個void *形參,用於接收這個引數,然後指向這個值的指標便傳遞給比較
函式,這個修改使字串和陣列物件也可以被使用,字串和陣列無法作為引數傳
遞給函式,但指向它們的指標可以.
使用這種技巧的函式叫"回撥函式(callback function);因為使用者把一個函式指標
作為引數傳遞給其他函式,後者將"回撥"使用者的函式.任何時候,如果你所編寫的
函式必須能夠在不同的時刻執行不同型別的工作或執行只能由函式呼叫者定義
的工作,你都可以使用這個技巧.許多視窗系統使用回撥函式連線多個動作,
如拖拽滑鼠和點選按鈕來指定使用者程式中的某個特定函式.
我們無法在這個上下文環境中為回撥函式編寫一個準確的原型,因為我們並不
知道進行比較的值的型別.事實上,我們需要查詢函式能作用於任何型別的值,
解決這個難題的方法是把引數型別宣告為"void *",表示"一個指向未知型別
的指標".
/*
**在一個單鏈表中查詢一個指定值的函式,它的引數是一個指向連結串列第一個節點
**的指標,一個指向我們需要查詢的值的指標和一個函式指標,它所指向的函式
**用於比較儲存於此連結串列中的型別的值.
*/
#include
#include "node.h"
Node* search_list(Node *node,void const *value,
int(*compare)(void const*,void const*))
{ while (node!=NULL)
{ if(compare(&node->value,value)==0) break;
node=node->link;
}
return node;
}