一、函數指標的數組
我們可以聲明一個函數指標的數組 例如
int (*testCases[10])();
將 testCases 聲明為一個擁有10個元素的數組,每個元素都是一個指向函數的函數指標,該函數沒有參數,傳回型別為 int
像數組testCases 這樣的聲明非常難讀,因為很難分析出函數類型與聲明的哪部分相關,在這種情況下使用 typedef名字可以使聲明更為易讀,例如 :
// typedefs 使聲明更易讀
//定義函數類型指標的 typedef
//PFV表示該變數是一個指向函數的函數指標的別名,相當於普通一個int
typedef int (*PFV)();
PFV testCases[10]; //類似int arr[10]; 聲明一個數組,數組的元素是指向上面PFV定義的函數的函數指標。
testCases 的這個聲明與前面的等價 。
由testCases的一個元素引用的函數調用如下 :
const int size = 10;
PFV testCases[size];
int testResults[size];
void runtests() {
for ( int i = 0; i < size; ++i )
// 調用一個數組元素
testResults[ i ] = testCases[ i ]();
}
函數指標的數組可以用一個初始化列表來初始化,該表中每個初始值都代表了一個與數組元素類型相同的函數,例如:
int lexicoCompare( const string &, const string & );
int sizeCompare( const string &, const string & );
//PFI2S 表示一個函數指標類型
typedef int ( *PFI2S )( const string &, const string & );
//聲明並初始化一個2個元素的函數指標數組
PFI2S compareFuncs[2] =
{
lexicoCompare,
sizeCompare
};
/************************************痛點***************************************
我們也可以聲明指向 compareFuncs 的指標 這種指標的類型是 指向函數指標數組的指標,聲明如下:
PFI2S (*pfCompare)[2] = &compareFuncs;
聲明可以分解為:
(*pfCompare)解引用操作符 * 把 pfCompare 聲明為指標,後面的[2]表示 pfCompare 是指向兩個元素數組的指標:
(*pfCompare)[2]
typedef PFI2S 表示數組元素的類型,它是指向函數的指標,該函數返回 int 有兩個 const string&型的參數,數組元素的類型與運算式&lexicoCompare的類型相同,也與 compareFuncs的第一個元素的類型相同, 此外,它還可以通過下列語句之一獲得
compareFuncs[ 0 ];
(*pfCompare)[ 0 ];
要通過 pfCompare 調用 lexicoCompare 程式員可用下列語句之一
// 兩個等價的調用
pfCompare[ 0 ]( string1, string2 ); // 編寫
((*pfCompare)[ 0 ])( string1, string2 ); // 顯式
***************************************痛點************************************/
二、參數和傳回型別
現在我們回頭看一下開始提出的問題,在那裡給出的任務要求我們寫一個排序函數,怎樣用函數指標寫這個函數呢? 因為函數參數可以是函數指標,所以我們把表示所用比較操作的函數指標作為參數傳遞給排序函數:
int sort( string*, string*, int (*)( const string &, const string & ) );
我們再次用 typedef名字使 sort()的聲明更易讀
// typedef 使 sort() 的聲明更易讀
typedef int ( *PFI2S )( const string &, const string & );
int sort( string*, string*, PFI2S );
因為在多數情況下使用的函數是 lexicoCompare(),所以我們讓它成為預設的函數指標參數
// 提供預設參數作為第三個參數
int lexicoCompare( const string &, const string & );
int sort( string*, string*, PFI2S = lexicoCompare );
sort()函數的定義可能像這樣
void sort( string *s1, string *s2,
PFI2S compare = lexicoCompare )
{
//…實現代碼
}
/************************************痛點***************************************
注意,除了用作參數類型之外,函數指標也可以被用作函數傳回值的類型,例如:
int (*ff( int ))( int*, int );
該聲明將 ff()聲明為一個函數,它有一個 int 型的參數,返回一個指向函數的指標,類型為
int (*) ( int*, int );
同樣,使用 typedef名字可以使聲明更容易讀懂 例如 下面的 typedef PF 使得我們能更
容易地分解出ff()的傳回型別是函數指標
// typedef 使聲明更易讀
typedef int (*PF)( int*, int );
PF ff( int );
函數不能聲明返回一個函數類型,如果是,則產生編譯錯誤,例如,函數ff()不能如下聲明:
// typedef 表示一個函數類型
typedef int func( int*, int );
func ff( int ); // 錯誤: ff()的返同類型為函數類型
***************************************痛點************************************/