C/C++函数指针与回调函数总结(函数指针数组)
? ? ? ? 函數有它的地址,程序運行起來了,程序里肯定有地方要放這個函數。我們知道可以用printf ?%p來輸出一個變量的地址,數組的地址,同樣我們定義了一個函數后,用這個函數的名字做輸出,就可以得到這個函數的地址。那么我們得到一個函數的地址,有什么用呢?
? ? ? ? 我們可以想一下,在程序里我們定義一個變量i,然后定義一個指針p,讓指針p指向i得到i的地址,然后通過*p我們就可以對i進行賦值等操作。那么,既然函數的名字可以得到函數地址,也就是說我們應該也可以用一個指針指向一個函數,得到函數的地址后,對函數做點事情,比如通過指針來調用這個函數?我們來試一下:
? ? ? ? 程序編譯通過了,但是給了一個warning,warning里說這個“函數指針的初始化是有矛盾的”。但是程序通過了編譯,也就是說我們是可以用一個指針指向一個函數的,只是初始化時沒有對應上類型,因為我們定義的指針p是int*類型,而函數是void()類型。找對類型還不夠,因為定義一個函數指針它還有特定的格式。
一、定義函數指針
定義函數指針的格式:例如:void?(*p)();
? ? ? ??void表示返回的類型,第二個括號是參數表。這樣格式的意思是我們定義了一個(*p)函數指針。之后我們就可以對它做初始化,比如讓它指向f函數:
? ? ? ? 這樣編譯程序就沒有了warning。那么定義了一個函數指針,我們讓它指向了函數f,之后我們怎樣調用指針里的內容?也就是調用指針所指的那個f函數?
二、調用函數指針
調用函數指針的格式:例如:(*p)();
我們來試一下這樣的方式調用函數指針p所指的那個函數:
? ? ? ? 在f函數里我們讓它輸出一句話,這樣當我們的函數指針成功調用所指的函數后,函數里的那句話就會被輸出,我們就知道函數調用成功了。
成功進入了f函數。
那么我們可以用函數指針來做些什么來使程序更方便靈活?
三、回調函數
????定義:把一個函數的指針作為參數傳遞到另一函數的參數表中,讓這個函數的指針被調用它所指的那個函數時,這種行為就是回調函數。也就是說這個指針函數的調用方式不是直接調用,而是在特定的條件下由另一方調用。
我們先來看這樣一個例子:
我們定義了一個f函數和一個g函數,兩個函數里分別做輸出。主函數里,第16和17行定義兩個函數指針一個指向f函數一個指向g函數。接下來第18行我們輸一個值給i,然后做判斷,如果i等于0就調用f函數,等于1就調用g函數。
可是這樣有一個缺點是,如果以后我們想在程序里加個新的函數進去,那么就要修改寫很多東西,比如在這個程序中,如果新添加一個h函數,當用戶輸入2時就調用h函數,那么就要在24行那里再加一個else if,這樣改動很麻煩。
要解決這個問題,我們可以用指針數組的方式:
再13行我們加了一個g函數,然后再主函數第21行中,我們定義了一個函數指針數組,(*fa[ ]),也就是這個數組里每一個元素都是一個指針。我們直接給它賦初值f,g,h。等程序22行輸入了一個數后,23行判斷,如果這個數是在有效范圍內,就進入if做響應的函數調用。(sizeof(fa)/sizeof(fa[0])得到該數組內元素的個數)。
這樣做的好處是如果以后程序要做修改,比如新添加一個函數,調用它的話就在數組里加一個指針指向該函數即可。這種方式可以做成一個程序根據你輸入的數去決定做什么事情,比如輸入不同的數就調用不同的函數。
我們來看第二個例子,自定義一個函數用一個指針指向另一個函數:
f函數里給兩個變量a和b,return a+b的值,g函數同樣給兩個變量a和b,return a-b的值。第13行我們定義一個h函數,函數要的參數是一個函數指針,并且這個函數指針的參數表里也要兩個變量。h函數里我們輸出這個函數指針所調用的那個函數,參數給2和3。在主函數中,第20行和21行分別用這個h函數調用f函數和g函數,得到的結果:
也就是說我們在程序中可以把一個函數當作一個值傳入另一個函數里,在另一個函數里根據這個傳入函數的值做事情。
第二個例子便是回調函數,回調函數的意義是,我們這個程序里的h函數所做的事情是固定的,就是輸出函數指針所指的函數運行后得到得值。h函數所做的事情是根據外面傳入的東西的不同而得到不同的結果。
?
其他實例一:
#include "stdafx.h" #include <iostream> using namespace std;typedef int(*pFun)(int); //定義一個函數指針類型 //函數功能:回調函數測試函數 //參數: pFun pCallback[IN] -- 函數指針,用于指針回調函數 //返回值: 無 void Caller(pFun pCallback) {cout << "準備執行回調函數..." << endl;int ret = pCallback(1);cout << "函數處理結果:" << ret << endl; }//函數功能:真正的回調函數 //參數: int iParam[IN] -- 輸入參數 //返回值: int -- 執行結果 int realCallbackFun(int iParam) {cout << "進入回調函數..." << endl;return iParam + 1; }int main(int argc, char* argv[]) {Caller(realCallbackFun);getchar();return 0; }?
其他實例二:
#include <iostream>using namespace std;int computer(int a, int b, int(*func)(int, int)) {return func(a, b); }int max(int a, int b) {return (a > b ? a : b); }int min(int a, int b) {return (a > b ? b : a); }int sum(int a, int b) {return a + b; }int main() {int a, b, res;cout << "請輸入整數a:"; cin >> a;cout << "請輸入整數b:"; cin >> b;res = computer(a, b, &max);cout << "Max of " << a << " and " << b << " is " << res << endl;res = computer(a, b, &min);cout << "Min of " << a << " and " << b << " is " << res << endl;res = computer(a, b, &sum);cout << "Sum of " << a << " and " << b << " is " << res << endl;return 0; }?
總結
以上是生活随笔為你收集整理的C/C++函数指针与回调函数总结(函数指针数组)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stat()函数:获取文件状态
- 下一篇: C/C++端口复用SO_REUSEADD