C/C++函數指針深入探究

函數指針

為什麼要使用函數指針?

  • 調用的靈活性和通用性。

試想一下,我們在設計初期並不知道我們的函數的具體實現細節。例如,我們我們想要一個排序函數qsort,但是具體排序法則我們並不確定,是降序還是升序,采用什麼算法都不清楚。這些問題是要在用戶調用這個函數的時候才能夠決定。於是調用者應該自己設計comparator函數,傳給qsort函數。

  • 便於面向對象編程。

例如我們設計一個結構體apple。我們除瞭設計出蘋果的屬性比如,數量、重量、顏色外,我們還要定義關於蘋果的操作,比如,吃掉,種植,這時候我們可以使用函數指針。然後我們以後調用這個結構體的時候,可以采用a.eat(&b)的方式調用函數。

typedef struct apple{
    int number;
    double weight;
    colorType color;
    //some operations
    bool (*eat)(struct apple*);
    bool (*plant)(struct apple*);
}apple;

語法

函數地址

函數的地址實際上就是函數名。這一點可以類比於數組。

聲明

要聲明指向特定類型的函數的指針,可以先編寫這種函數的原型,然後用(*pf)代替函數名。或者采用C++11 的auto也能聲明並初始化函數指針。

double pam (int);
//這是函數原型
double (*pf)(int);
//這是函數指針
auto pn=pam;
//定義並初始化函數指針

使用函數指針調用函數

double pam (int);
//這是函數原型
double (*pf)(int);
//這是函數指針
auto pn=pam;
//定義並初始化函數指針
pf=pam;
pam(4);
(*pf)(4);
(*pn)(4);

直接把函數地址(即函數名)賦值給函數指針就行瞭,註意特征標和返回類型必須相同。然後采用(*pf)(4)這樣的方式調用函數。實際上,C++也允許這樣子使用函數指針:

pf(4);//這種形式好看且實用,但是沒有顯示出 使用函數指針調用函數
pn(4);

深入理解函數指針

閱讀這一篇幅,需要您熟練掌握,C語言中的指針。

//一些函數原型
const double* f1(const double ar[],int n);
const double* f2(const double *,int);
const double* f3(const double *,int);
//函數指針
const double* (*p1)(const double ar[],int n)=f1;
auto p2=f2;//感謝auto
//調用函數
cout<<(*p1)(av,3)<<*(*p1)(av,3);
cout<<p2(av,3)<<*p2(av,3);
//實際上 *p2(av,3)和*(*p2)(av,3)是一樣的。不理解的看上面內容。
//包含3個函數指針的數組
const double* (*pa[3])(const double *,int)={f1,f2,f3};
//註意:
//1、[]優先級高於* 所以這是個數組不是指針。
//2、不能使用auto定義並初始化列表
auto pb=pa;
//既然已經聲明瞭數組,數組名就是指針,采用auto可以定義初始化指針,這是合法的。
//調用函數
double x=*pa[0](av,3);
double y=*(*pb[1])(av,3);//由於[]優先級高於* 所以pb[1]是個函數指針。然後(*pb[1])就是調用函數瞭。
//更加深入
const double *(*(*pd)[3])(const double *,int) = &pa;
//首先把函數指針的殼子去掉即 const double *(* ···)(const double *,int),然後得到(*pd)[3]這裡 pd先和* 結合 再和[]結合,所以pd是個指針,這個指針指向一個數組,這個數組的元素又是函數指針。
//是不是特別繞?
//感謝auto
auto pc=&pa;
//調用
(*pd)[0](av,3);
//pd是指向數組的指針,則(*pd)[0]就是數組的元素,數組的元素是函數指針,所以可以采用這種方式調用函數。
//或者采用  (*(*pd)[0])(av,3)調用函數也是等價的。
double z=*(*pd)[0](av,3);
//或者 采用 double z=*(*(*pd)[0])(av,3) 也是等價的

我們對於語法的瞭解不能僅僅潛於認識,對於這種const double *(*(*pd)[3])(const double *,int) = &pa; 我們不光要認識,更要會使用,再次重溫一遍,我們想要一個指向數組的指針,這個數組裡的元素是函數指針。

第一步,數組元素的類型是函數指針,所以殼子要有 const double *(* ···)(const double *,int)

第二步,指向數組的指針 (*pd)[3] ,由於[]比*優先級高,所以我們必須采用(),否則 *pd[3] 就是一個數組,數組的元素是指針。 第三步,結合得 const double *(*(*pd)[3])(const double *,int) = &pa

使用typedef 簡化

typedef const double *(* p_fun)(const double *,int);
p_fun p1=f1;
p_fun pa[3]={f1,f2,f3};
p_fun (*pd)[3]=&pa;

typedef 使得代碼量減少很多,而且更容易理解

到此這篇關於C/C++函數指針深入探究的文章就介紹到這瞭,更多相關C++函數指針內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: