天天看點

C/C++函數指針用法總結



                               C++函數指針

一 函數指針介紹

  函數指針指向某種特定類型,函數的類型由其參數及傳回類型共同決定,與函數名無關。舉例如下:

int add(int nLeft,int nRight);//函數定義
           

 該函數類型為int(int,int),要想聲明一個指向該類函數的指針,隻需用指針替換函數名即可:

int (*pf)(int,int);//未初始化
           

  則pf可指向int(int,int)類型的函數。pf前面有*,說明pf是指針,右側是形參清單,表示pf指向的是函數,左側為int,說明pf指向的函數傳回值為int。則pf可指向int(int,int)類型的函數。而add類型為int(int,int),則pf可指向add函數。

pf = add;//通過指派使得函數指針指向某具體函數
           

  注意:*pf兩端的括号必不可少,否則若為如下定義:

int *pf(int,int);//此時pf是一個傳回值為int*的函數,而非函數指針
           

二 标準C函數指針

 1函數指針的定義

   1.1 普通函數指針定義

int (*pf)(int,int);
           

  1.2 使用typedef定義函數指針類型

typedef int (*PF)(int,int);
      PF pf;//此時,為指向某種類型函數的函數指針類型,而不是具體指針,用它可定義具體指針</span>
           

 2函數指針的普通使用

pf = add;
     pf(100,100);//與其指向的函數用法無異
     (*pf)(100,100);//此處*pf兩端括号必不可少
           

注意:add類型必須與pf可指向的函數類型完全比對

 3函數指針作為形參

//第二個形參為函數類型,會自動轉換為指向此類函數的指針
     Void fuc(int nValue,int pf(int,int));

     //等價的聲明,顯示的将形參定義為指向函數的指針
     Void fuc(int nValue,int (*pf)(int,int));
     Void fuc(int nValue,PF);
           

     形參中有函數指針的 函數調用,以fuc為例:

pf = add;//pf是函數指針
      fuc(1,add);//add自動轉換為函數指針
      fuc(1,pf);
           

 4傳回指向函數的指針

4.1 使用typedef定義的函數指針類型作為傳回參數

PF fuc2(int);//PF為函數指針類型
           

    4.2 直接定義函數指針作為傳回參數

int (*fuc2(int))(int,int);//顯示定義
           

   說明:按照有内向外的順序閱讀此聲明語句。fuc2有形參清單,則fuc2是一個函數,其形參為fuc2(int),fuc2前面有*,是以fuc2傳回一個指針,指針本身也包含形參清單(int,int),是以指針指向函數,該函數的傳回值為int.

總結:fuc2是一個函數,形參為(int),傳回一個指向int(int,int)的函數指針。

二 C++函數指針

 1由于C++完全相容C,則C中可用的函數指針用法皆可用于C++

 2 C++其他函數(指針)定義方式及使用

2.1 typedef與decltype組合定義函數類型

typedef decltype(add) add2;
           

  decltype傳回函數類型,add2是與add相同類型的函數,不同的是add2是類型,而非具體函數。

使用方法:

add2* pf;//pf指向add類型的函數指針,未初始化
           

    2.2 typedef與decltype組合定義函數指針類型

typedef decltype(add)* PF2;//PF2與1.1PF意義相同
           
PF2 pf;// pf指向int(int,int)類型的函數指針,未初始化
           

    2.3 使用推斷類型關鍵字auto定義函數類型和函數指針

auto pf = add;//pf可認為是add的别名(個人了解) 
       auto *pf = add;//pf為指向add的指針 
           

 3函數指針形參

typedef decltype(add) add2;
   typedef decltype(add)* PF2;
   void fuc2 (add2 add);//函數類型形參,調用自動轉換為函數指針
   void fuc2 (PF2 add);//函數指針類型形參,傳入對應函數(指針)即可
           

     說明:不論形參聲明的是函數類型:void fuc2 (add2 add);還是函數指針類型void fuc2 (PF2 add);都可作為函數指針形參聲明,在參數傳入時,若傳入函數名,則将其自動轉換為函數指針。

 4  傳回指向函數的指針

    4.2 使用auto關鍵字      

auto fuc2(int)-> int(*)(int,int) //fuc2傳回函數指針為int(*)(int,int) 
           

4.2 使用decltype關鍵字

decltype(add)* fuc2(int)//明确知道傳回哪個函數,可用decltype關鍵字推斷其函數類型,
           

  5 成員函數指針

 5.1普通成員函數指針使用舉例    

class A//定義類A
{
private:

       int add(int nLeft, int nRight)

       {
              return (nLeft + nRight);
       }

public:

       void fuc()

       {
              printf("Hello  world\n");
           
       }
};

 
typedef void(A::*PF1)();//指針名前需加上類名限定

PF1 pf1 = &A::fuc; //必須有&

A a;//成員函數位址解引用必須附駐與某個對象位址,是以必須建立一個隊形

(a.*pf1)();//使用成員函數指針調用函數
           

     5.2繼承中的函數指針使用舉例

class A
{
public:
       void fuc()
       {
              printf("Hello fuc()\n");
       }

       void fuc2()
       {
              printf("Hello A::fuc2()\n");
       }
};

class B:public A
{
public:
       virtual void fuc2()
       {
              printf("Hello B::fuc2()\n");
       }

};

typedef void(A::*PF1)();
typedef void(B::*PF2)();

PF1 pf1 = &A::fuc;

int main()       
{
       A a;
       B b;
       (a.*pf1)();  //調用A::fuc
       (b.*pf1)();   //調用A::fuc

       pf1 = &A::fuc2;
       (a.*pf1)();  //調用A::fuc2
       (b.*pf1)();  //調用A::fuc2

       PF2 pf2 = &A::fuc2; 
       (b.*pf2)(); //調用A::fuc2
}
           

  6重載函數的指針

    6.1 重載函數fuc

Void fuc();
    Void fuc(int);
           

  6.2 重載函數的函數指針

void (*PF)(int) = fuc;//PF指向fuc(int)
   int(*pf2)(int) = fuc;//錯誤沒有比對的類型
           

   注意:編譯器通過指針類型決定選取那個函數,指針類型必須與重載函數中的一個精确比對。