- 函數指針
- 一個函數總是占用一段連續的內存區域,函數名在表達式中有時會被轉換成該函數所在區域的首地址,這和數組名非常類似。
- 我們可以把函數的這個首地址(或稱入口地址)賦予一個指針變量,使指針變量指向函數所在的內存區域,然后通過指針變量就可以找到並調用該函數。
函數的類型由它的返回類型和形參類型共同決定,與函數名無關。
bool lengthCompare(const string &, const string &);
//該函數的類型是bool (const string &, const string &)。
bool (*pf) (const string &, const string &);
//pf指向一個函數,該函數的參數是兩個const string的引用,返回值是bool類型
1. 使用函數指針
當我們把函數名作為一個值使用時,該函數自動轉換成指針。
pf = lengthCompare; //pf指向名為lengthCompare的函數
pf = &lengthCompare; //等價的賦值語句:取地址符是可選的
使用函數指針調用函數:
bool b1 = pf("hello", "goodbye"); //調用lengthCompare函數
bool b2 = (*pf) ("hello", "goodbye"); //一個等價的調用
bool b3 = lengthCompare("hello", "goodbye"); //另一個等價的調用
我們可以為函數指針賦一個nullptr或者值為0的整型常量表達式,表示該指針沒有指向任何一個函數。
2. 函數指針形參
雖然不能定義函數類型的形參,但是形參可以是指向函數的指針。此時,形參看起來是函數類型,實際上卻是當成指針使用:
//第三個形參是函數類型,它會自動轉換成指向函數的指針
void useBigger(const string &s1, const string &s2, bool pf (const string &, const string &));
//等價的聲明:顯式的將形參定義成指向函數的指針
void useBigger(const string &s1, const string &s2, bool (*pf) (const string &, const string &));
//可以直接將函數作為實參使用,此時它會自動轉換成指針
useBigger(s1, s2, lengthCompare);
3. 返回指向函數的指針
和數組一樣,雖然不能返回一個函數,但是能返回指向函數類型的指針。然而,我們必須把返回類型寫成指針形式。
想要聲明一個返回函數指針的函數,最簡單的方法是使用類型別名:
using F = int(int *, int); //F是函數類型,不是指針
using PF = int(*)(int *, int); //PF是指針類型
PF f1(int); //正確:PF是指向函數的指針,f1返回指向函數的指針
F f1(int); //錯誤:F是函數類型,f1不能返回一個函數
F *f1(int); //正確:顯式的指定返回類型是指向函數的指針