函數調用是C++中再頻繁不過的一項操作了,函數可以直接調用,也可以通過函數指針來調用,也可以通過函數對象來間接調用,形式多樣化。下面來看看函數指針和函數對象的區別。
1.函數指針
1)定義
函數指針是指向函數的指針變量。在C編譯時,每一個函數都有一個入口地址,那麼這個指向這個函數的函數指針便指向這個地址。函數指針主要有兩個作用:用作調用函數和做函數的參數。
2)聲明方法
數據類型標志符 (指針變量名) (形參列表);
一般函數的聲明為: int fun( int x ); 而一個函數指針的聲明方法為:int (*fun) (int x);
前面的那個(*fun)中括號是必要的,這會告訴編譯器我們聲明的是函數指針而不是聲明一個具有返回型為指針的函數,後面的形參要視這個函數指針所指向的函數形參而定。
然而這樣聲明我們有時覺得非常繁瑣,於是 typedef 可以派上用場了,我們也可以這樣聲明:
typedef int (*pf) (int x);
pf p;
這樣 p 便是一個函數指針。當要使用函數指針來調用函數時,fun(x)、(*fun)(x) 就可以了,當然,函數指針也可以指向被重載的函數,編譯器會為我們區分這些重載的函數從而使函數指針指向正確的函數。
Demo:
typedef void (*P) ( char ,int );
void bar(char ch, int i) {
cout<<"bar "<<ch<<' '<<i<<endl;
return ;
}
P p;
p = bar;
(*p)('e',91); // 或 p('e',91);
例子中函數指針p指向了一個已經聲明的函數bar(),然後通過p來調用函數。
函數指針另一個作用便是作為函數的參數,我們可以在一個函數的形參列表中傳入一個函數指針,然後便可以在這個函數中使用這個函數指針所指向的函數,這樣便可以使程序變得更加清晰和簡潔,而且這種用途技巧可以幫助我們解決很多棘手的問題,使用很小的代價就可獲得足夠大的利益(速度+復雜度)。
Demo:
// 核心內容,非完整程序
typedef void (*P) ( char ,int );
void bar(char ch, int i) {
cout<<"bar "<<ch<<' '<<i<<endl;
return ;
}
void foo(char ch, int i, P p) {
(*p)(ch,i);
return ;
}
int main() {
P p;
p = bar;
foo('e',12,p);
}
上述例子我們首先利用一個函數指針p指向bar(),然後在foo()函數中使用p指針來調用bar(),實現目的。將這個特點稍加利用,我們就可以構造出強大的程序,只需要同樣的foo函數便可以實現對不同bar函數的調用。