C/C++函數(shù)指針深入探究
函數(shù)指針
為什么要使用函數(shù)指針?
- 調(diào)用的靈活性和通用性。
試想一下,我們在設(shè)計初期并不知道我們的函數(shù)的具體實現(xiàn)細(xì)節(jié)。例如,我們我們想要一個排序函數(shù)qsort,但是具體排序法則我們并不確定,是降序還是升序,采用什么算法都不清楚。這些問題是要在用戶調(diào)用這個函數(shù)的時候才能夠決定。于是調(diào)用者應(yīng)該自己設(shè)計comparator函數(shù),傳給qsort函數(shù)。
- 便于面向?qū)ο缶幊獭?/li>
例如我們設(shè)計一個結(jié)構(gòu)體apple。我們除了設(shè)計出蘋果的屬性比如,數(shù)量、重量、顏色外,我們還要定義關(guān)于蘋果的操作,比如,吃掉,種植,這時候我們可以使用函數(shù)指針。然后我們以后調(diào)用這個結(jié)構(gòu)體的時候,可以采用a.eat(&b)的方式調(diào)用函數(shù)。
typedef struct apple{
int number;
double weight;
colorType color;
//some operations
bool (*eat)(struct apple*);
bool (*plant)(struct apple*);
}apple;語法
函數(shù)地址
函數(shù)的地址實際上就是函數(shù)名。這一點可以類比于數(shù)組。
聲明
要聲明指向特定類型的函數(shù)的指針,可以先編寫這種函數(shù)的原型,然后用(*pf)代替函數(shù)名?;蛘卟捎肅++11 的auto也能聲明并初始化函數(shù)指針。
double pam (int); //這是函數(shù)原型 double (*pf)(int); //這是函數(shù)指針 auto pn=pam; //定義并初始化函數(shù)指針
使用函數(shù)指針調(diào)用函數(shù)
double pam (int); //這是函數(shù)原型 double (*pf)(int); //這是函數(shù)指針 auto pn=pam; //定義并初始化函數(shù)指針 pf=pam; pam(4); (*pf)(4); (*pn)(4);
直接把函數(shù)地址(即函數(shù)名)賦值給函數(shù)指針就行了,注意特征標(biāo)和返回類型必須相同。然后采用(*pf)(4)這樣的方式調(diào)用函數(shù)。實際上,C++也允許這樣子使用函數(shù)指針:
pf(4);//這種形式好看且實用,但是沒有顯示出 使用函數(shù)指針調(diào)用函數(shù) pn(4);
深入理解函數(shù)指針
閱讀這一篇幅,需要您熟練掌握,C語言中的指針。
//一些函數(shù)原型
const double* f1(const double ar[],int n);
const double* f2(const double *,int);
const double* f3(const double *,int);
//函數(shù)指針
const double* (*p1)(const double ar[],int n)=f1;
auto p2=f2;//感謝auto
//調(diào)用函數(shù)
cout<<(*p1)(av,3)<<*(*p1)(av,3);
cout<<p2(av,3)<<*p2(av,3);
//實際上 *p2(av,3)和*(*p2)(av,3)是一樣的。不理解的看上面內(nèi)容。
//包含3個函數(shù)指針的數(shù)組
const double* (*pa[3])(const double *,int)={f1,f2,f3};
//注意:
//1、[]優(yōu)先級高于* 所以這是個數(shù)組不是指針。
//2、不能使用auto定義并初始化列表
auto pb=pa;
//既然已經(jīng)聲明了數(shù)組,數(shù)組名就是指針,采用auto可以定義初始化指針,這是合法的。
//調(diào)用函數(shù)
double x=*pa[0](av,3);
double y=*(*pb[1])(av,3);//由于[]優(yōu)先級高于* 所以pb[1]是個函數(shù)指針。然后(*pb[1])就是調(diào)用函數(shù)了。
//更加深入
const double *(*(*pd)[3])(const double *,int) = &pa;
//首先把函數(shù)指針的殼子去掉即 const double *(* ···)(const double *,int),然后得到(*pd)[3]這里 pd先和* 結(jié)合 再和[]結(jié)合,所以pd是個指針,這個指針指向一個數(shù)組,這個數(shù)組的元素又是函數(shù)指針。
//是不是特別繞?
//感謝auto
auto pc=&pa;
//調(diào)用
(*pd)[0](av,3);
//pd是指向數(shù)組的指針,則(*pd)[0]就是數(shù)組的元素,數(shù)組的元素是函數(shù)指針,所以可以采用這種方式調(diào)用函數(shù)。
//或者采用 (*(*pd)[0])(av,3)調(diào)用函數(shù)也是等價的。
double z=*(*pd)[0](av,3);
//或者 采用 double z=*(*(*pd)[0])(av,3) 也是等價的我們對于語法的了解不能僅僅潛于認(rèn)識,對于這種const double *(*(*pd)[3])(const double *,int) = &pa; 我們不光要認(rèn)識,更要會使用,再次重溫一遍,我們想要一個指向數(shù)組的指針,這個數(shù)組里的元素是函數(shù)指針。
第一步,數(shù)組元素的類型是函數(shù)指針,所以殼子要有 const double *(* ···)(const double *,int)
第二步,指向數(shù)組的指針 (*pd)[3] ,由于[]比*優(yōu)先級高,所以我們必須采用(),否則 *pd[3] 就是一個數(shù)組,數(shù)組的元素是指針。 第三步,結(jié)合得 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 使得代碼量減少很多,而且更容易理解
到此這篇關(guān)于C/C++函數(shù)指針深入探究的文章就介紹到這了,更多相關(guān)C++函數(shù)指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言基礎(chǔ)隱式類型轉(zhuǎn)換與強制類型轉(zhuǎn)換示例解析
最接地氣的有關(guān)類型轉(zhuǎn)換的介紹,此處對于類型轉(zhuǎn)換的相關(guān)知識點做一些簡要的介紹,作者實屬初學(xué),難免文章中有內(nèi)容理解不到位或者有不當(dāng)之處,還請朋友們不吝指正,希望大家多多給予支持2021-11-11
QT布局管理詳解QVBoxLayout與QHBoxLayout及QGridLayout的使用
在這篇文章中,你將知道水平布局、垂直布局、網(wǎng)格布局如何輕松上手,以純代碼方式展示。對齊方式,大小設(shè)置,圖片頭像匹配標(biāo)簽,布局器里面的組件大小隨意切換大小,認(rèn)真看完這篇文章,QT布局管理器熟練使用2022-06-06
C語言動態(tài)內(nèi)存管理的實現(xiàn)示例
動態(tài)內(nèi)存管理是一種允許程序在運行時根據(jù)需要動態(tài)申請和回收內(nèi)存的策略,它提供了四種重要的函數(shù),本文就來介紹一下,感興趣的可以了解一下2024-11-11
C語言數(shù)據(jù)結(jié)構(gòu)之雙鏈表&循環(huán)鏈表&靜態(tài)鏈表詳解
這篇文章主要為大家詳細(xì)介紹了C語言數(shù)據(jù)結(jié)構(gòu)中雙鏈表&循環(huán)鏈表&靜態(tài)鏈表的原理與使用,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-09-09
C++基礎(chǔ)入門教程(九):函數(shù)指針之回調(diào)
這篇文章主要介紹了C++基礎(chǔ)入門教程(九):函數(shù)指針之回調(diào),本文講解了函數(shù)的地址、聲明函數(shù)指針、歷史原因、typedef挽救復(fù)雜的函數(shù)指針等內(nèi)容,需要的朋友可以參考下2014-11-11

