函數指針是C++中經常用到的指針類型,對業務解耦合有着重要的意義,學習函數指針,首先應該學習數組類型,兩者在定義上大同小異,所以,先來回顧一下數組類型的用法吧!
1 數組類型
數組類型的使用主要涉及三個定義:
- 如何定義一個數組類型
- 如何定義一個數組指針類型
- 如何定義一個指向數組類型的指針變量
我在代碼中詳細註釋了數組類型、數組指針類型以及指向數組類型的指針變量的定義方法,如下:
#include <stdio.h>
#include <string.h>
#include "stdlib.h"
int main()
{
//定義一個數組 int array[10]
//定義一個數組類型
typedef int (MyArrayType)[10];
//用這個類型定義一個變量
MyArrayType array0;//相當於 int array[10];
array0[0] = 2;
//定義一個數組指針類型
int array1[10];
typedef int (*PMyArrayType)[10];
PMyArrayType pmyArray;
pmyArray = &array1;
(*pmyArray)[0] = 3;
//定義一個指向數組類型的指針變量
int array2[10];
int (*pMyArray)[10]; //告訴編譯器分配四個字節的內存
pMyArray = &array2;
(*pMyArray)[0] = 4;
//打印結果
printf("數組類型輸出:%d\n", array0[0]);
printf("數組指針類型輸出:%d\n", array1[0]);
printf("指向數組類型指針變量輸出:%d\n", array2[0]);
return 0;
}
輸出結果如下圖:
2 函數指針
同數組類型相似,函數指針也是三個定義:
- 如何定義一個函數類型
- 如何定義一個函數指針類型
- 如何定義一個指向函數的指針變量
同上,代碼中詳細註釋了這三種定義方法及它們的使用方法,如下:
#include <stdio.h>
#include <string.h>
#include "stdlib.h"
//test是函數名,函數名是函數首地址,函數名就是函數指針
//對函數地址取多少次地址結果都還是函數地址
int test(int a)
{
printf("a=%d\n",a);
return 0;
}
int main()
{
//定義一個函數類型
typedef int (MyFuncType)(int);
MyFuncType *myfunc = test;
printf("輸出函數類型:");
(*myfunc)(2);
//定義函數指針類型
typedef int (*PMyFuncType)(int);
PMyFuncType pmyFunc = test;
printf("輸出函數指針類型:");
(*pmyFunc)(3);
//定義一個指向函數的指針變量
int (*PmyFunc)(int); //告訴編譯器分配四個字節
PmyFunc = test;
printf("輸出指向函數指針類型指針變量:");
(*PmyFunc)(4);
return 0;
}
輸出結果如下圖:
3 函數指針作函數參數
函數指針作函數參數是函數指針最重要的使用,通過一段代碼來學習,如下:
#include <stdio.h>
#include <string.h>
#include "stdlib.h"
int add(int a, int b)
{
int c;
c = a + b;
return c;
}
int MyPrint(int (*pMyAdd)(int,int))
{
printf("函數指針作函數參數:%d\n", pMyAdd(2,3));
}
//聲明一個函數指針類型
//函數指針作函數參數不光把函數的入口地址給了被調函數,同時作了接口的約定
typedef int (*PMyFuncType)(int,int);
int MyPrint1(PMyFuncType pMyFunc)
{
printf("函數指針作函數參數:%d\n", pMyFunc(7,8));
}
int main()
{
//定義一個函數指針變量
int (*pAdd)(int,int);
pAdd = add;
//MyPrint方法
MyPrint(pAdd);
//MyPrint1方法
MyPrint1(pAdd);
return 0;
}
輸出結果如下圖:
函數指針作函數參數最重要的目的就是解耦合,即將寫任務和調用任務的人分開,它的使用一般有兩種情況,稱爲函數指針的正反向調用。
- 正向調用:應用程序EXE調用動態庫
- 反向調用:動態庫反向調用應用程序,在動態庫中通過函數指針實現業務模型的抽象
以動態庫爲例重點說明一下反向調用的使用方法,主要分爲兩步:
- 動態庫提前定義業務模型接口
- 提前把應用層的函數入口地址注入到動態庫
比如在動態庫中抽象一個加密模型,如下:
typedef int (*EncData)(unsigned char *inData, int inDataLen, unsigned char *outData, int outDataLen, void *Ref, int RefLen);
然後只需要在動態庫中調用此函數,而這個函數的真實實現由應用層完成,應用層將函數地址和參數傳遞給動態庫即可,通過這種解耦合的方法,當業務需求發生更改時,就無需再次改動動態庫。
以上。