天天看點

C++ 7.9 指向函數的指針

簡介

===========================================================================================================

一、指向函數的指針

  • 函數指針是指指向函數而非指向對象的指針,像其他指針一樣,函數指針也指向某個特定的類型。函數類型由其傳回類型以及形參表确定,而與函數名無關;
bool (*pf)(const string &,const string &);
//這個語句将pf 聲明為指向函數的指針,它所指向的函數帶有兩個const string & 類型的形參和bool 類型的傳回值。

//指針兩邊的 圓括号是必須的
           

1、用typedef 簡化函數指針的定義

  • 函數指針類型相當地冗長。使用typedef 為指針類型定義同義詞,可将函數指針的使用大大簡介。

typedef bool (* cmpFcn)(const string &,const string &);

要使用這種函數指針類型時,隻需直接使用cmpFcn 即可,不必每次都把整個類型聲明全部寫出來。

2、指向函數的指針的初始化和指派

  • 在引用函數名但又沒有調用該函數時,函數名将自動解釋為指向函數的指針。假設有函數:
bool lengthCompare(const string &,const string &);
           

除了用作函數調用的左操作數以外,對lengthCompare的任何使用都被解釋為如下類型的指針;

bool (*)(const string &,const string &);
           

可使用函數名對函數指針做初始化和指派:

cmpFcn pf1 = ; //cmpFcn是一個指向函數的指針類型,是以pf1是一個函數指針,但是還沒有綁定到一個函數
cmpFcn pf2 = lengthCompare;//函數指針pf2指向函數lengthCompare,他們的類型完全比對
pf1=lengthCompare;
pf2=pf1;//可以函數指針之間的指派
           

此時,直接引用函數名等效于在函數名上應用取位址操作符:

cmpFcn pf1 = lengthCompare;
cmpFcn pf2 = &lengthCompare;

           

注意:

  • 函數指針隻能通過同類型的函數或函數指針或0值常量表達式進行初始化或指派。
  • 将函數指針初始化為0 ,表示該指針不指向任何函數。
  • 指向不同函數類型的指針之間不存在轉換**
string::size_type sumLength(const string&,const string&);
bool cstringCompare(char*,char*);
cmpFcn pf;//定義了一個函數指針
pf=sumLength;//錯誤!!!!
pf=cstringCompare;//錯誤!!!
pf=lengthCompare;//可以,函數指針和函數類型比對
           

3、通過指針調用函數

  • 指向函數的指針可用于調用它所指向的函數。可以不需要使用解引用操作符,直接通過指針調用函數:
  • 如果指向函數的指針沒有初始化,或者具有0 值,則該指針不能在函數調用中使用。
  • 隻有當指針已經初始化,或被指派為指向某個函數,方能安全地用來調用函數。
cmpFcn pf=lengthCompare;//函數指針pf指向函數lengthCompare
lengthCompare("hi","bye");//函數調用
pf("hi","bye"); //通過函數指針來調用所指向的函數
           

4、函數指針形參

  • 函數的形參可以是指向函數的指針。形參可以用以下兩種形式編寫:
void useBigger(const string &,const string &,bool(const string &,const string &));

void useBigger(const string &,const string &,bool(*)(const string &,const string &));
           

5、傳回指向函數的指針

  • 函數可以傳回指向函數的指針,但是正确寫這種傳回類型相對不易;
  • 閱讀函數指針聲明的最佳方法是從聲明的名字開始由裡而外了解。
  • 允許将形參定義為函數類型,但函數的傳回類型則必須是指向函數的指針,而不是函數。
  • 具有函數類型的形參所對應的實參将被自動轉化為指向相應函數類型的指針,但是,當傳回的是函數時,同樣的轉換操作無法實作

(沒怎麼懂!!!)

int (*ff(int))(int *,int);
//ff(int),将ff聲明為一個函數,它帶有一個int型的形參。該函數傳回 int(*)(int *,int);它是一個指向函數的指針,所指向的函數傳回int型并帶有兩個分别是int * 型和int 型的形參。
           

使用typedef可使該定義更簡明

typedef int (*PF)(int *,int);//PF是一種指向函數的指針類型
PF ff(int);  //函數ff的傳回類型是函數指針
           
typedef int func(int *,int);//func是一種函數類型,不是指向函數的指針
void f1(func);//聲明了一個函數f1,裡面有一個形參是func,是函數類型。函數沒有傳回類型
func f2(int);//錯誤!!!因為傳回類型是函數類型,形參卻是int型
func *f3(int);//可以,函數傳回一個指向函數類型的指針
           

6、指向重載函數的指針

extern void ff(vector<double>);
extern void ff(unsigned int);
void (*pf1)(unsigned int) = &ff;//函數指針pf1 指向函數ff(unsigned)

void (*pf2)(int) = &ff;//錯誤!!!參數類型不比對
double (*pf3)(vector<double>);  //錯誤!!!傳回類型不比對
pf3 = &ff;