函式指標(function pointer)

函式本身在記憶體中也佔有一個空間,而函式名稱是指向該空間位址的參考名稱,呼叫函式時,程式就會去執行該函式名稱所指向的記憶體空間中之指令。

我們可以宣告函式指標,讓它與某個函式指向相同的空間,做相同的事情,函式指標的宣告方式如下所示,函式指標可指向有相同型態的函式,也就是具有相同的回傳型態和參數型態的函式。
回值型態 (*指標名稱)(傳遞參數);

下面程式是個簡單的函式指標使用,函式指標ptr和fun()的位址相同,作用也相同。

#include<iostream>
using namespace std; 

int fun(); 

int main() { 
    int (*ptr)() = fun; 

    int addr1 = (int)fun;  //addr1=12652904
    int addr2 = (int)ptr;  //addr2=12652904

    fun();  //印出"hello"
    ptr();  //印出"hello"

    return 0; 
} 

int fun() { 
    cout<<"hello"<

函式指標可以讓程式更有彈性時,像假如要撰寫一個排序sort()函式,排序可以由大至小、由小至大,或其他排列方式,直觀上可能寫好幾個類似函式,分別是由小至大、由大至小,或其他排序方式,但比較有彈性的作法是在sort()上加上一個額外的參數,這個額外的參數傳入一個函式指標,由這個指標來決定排序的依據,這樣我們就不用寫好幾個sort()函式。

以下為實際的程式碼,使用關鍵字typedef,讓CMP成為此函式指標的別名,讓程式碼看起來更簡潔,當然這跟傳入實際的函式指標會得到相同的結果。

typedef bool (*CMP)(int, int);
void swap(int &, int &);
bool larger(int a, int b);
bool smaller(int a, int b);
void sort(int *arr, int length, CMP);

int main() { 
    int arr[] = {2, 7, 9, 1};
    sort(arr, 4, larger);  //排序後arr為{9,7,2,1}
    sort(arr, 4, smaller); //排序後arr為{1,2,7,9}
    return 0; 
} 

void swap(int &a, int &b){
    int t = a; 
    a = b; 
    b = t;
}
bool larger(int a, int b){
    return a>b;
}
bool smaller(int a, int b){
    return a>b;
}
void sort(int *arr, int length, CMP compare){
    for(int i=0; i < length-1; i++){
        for(int j=0; j < length-i-1; j++) { 
            if(compare(arr[j+1], arr[j])) { 
                swap(arr[j+1], arr[j]); 
            } 
        } 
    } 
}