篇一、函數指標
函數指標:是指向函數的指標變數,在C編譯時間,每一個函數都有一個入口地址,那麼這個指向這個函數的函數指標便指向這個地址。
函數指標的用途是很大的,主要有兩個作用:用作調用函數和做函數的參數。
函數指標的聲明方法:
資料類型標誌符 (指標變數名) (形參列表);
一般函數的聲明為:
int func ( int x );
而一個函數指標的聲明方法為:
int (*func) (int x);
前面的那個(*func)中括弧是必要的,這會告訴編譯器我們聲明的是函數指標而不是聲明一個具有返回型為指標的函數,後面的形參要視這個函數指標所指向的函數形參而定。
然而這樣聲明我們有時覺得非常繁瑣,於是typedef可以派上用場了,我們也可以這樣聲明:
typedef int (*PF) (int x);
PF pf;
這樣pf便是一個函數指標,方便了許多。當要使用函數指標來調用函數時,func(x)或者 (*fucn)(x) 就可以了,當然,函數指標也可以指向被重載的函數,編譯器會為我們區分這些重載的函數從而使函數指標指向正確的函數。
例子:
複製代碼 代碼如下:
typedef void (*PFT) ( char ,int );
void bar(char ch, int i)
{
cout<<"bar "<<ch<<' '<<i<<endl;
return ;
}
PFT pft;
pft = bar;
pft('e',91);
例子中函數指標pft指向了一個已經聲明的函數bar(),然後通過pft來實現輸出字元和整型的目的。
函數指標另一個作用便是作為函數的參數,我們可以在一個函數的形參列表中傳入一個函數指標,然後便可以在這個函數中使用這個函數指標所指向的函數,這樣便可以使程式變得更加清晰和簡潔,而且這種用途技巧可以協助我們解決很多棘手的問題,使用很小的代價就可獲得足夠大的利益(速度+複雜度)。
複製代碼 代碼如下:
typedef void (*PFT) ( char ,int );
void bar(char ch, int i)
{
cout<<"bar "<<ch<<' '<<i<<endl;
return ;
}
void foo(char ch, int i, PFT pf)
{
pf(ch,i);
return ;
}
PFT pft;
pft = bar;
foo('e',12,pft);
上述例子我們首先利用一個函數指標pft指向bar(),然後在foo()函數中使用pft指標來調用bar(),實現目的。將這個特點稍加利用,我們就可以構造出強大的程式,只需要同樣的foo函數便可以實現對不同bar函數的調用。
篇二、函數對象
前面是函數指標的應用,從一般的函數回調意義上來說,函數對象和函數指標是相同的,但是函數對象卻具有許多函數指標不具有的有點,函數對象使程式設計更加靈活,而且能夠實現函數的內聯(inline)調用,使整個程式實現效能加速。
函數對象:這裡已經說明了這是一個對象,而且實際上只是這個對象具有的函數的某些功能,我們才稱之為函數對象,意義很貼切,如果一個對象具有了某個函數的功能,我們變可以稱之為函數對象。
如何使對象具有函數功能呢,很簡單,只需要為這個對象的操作符()進行重載就可以了,如下:
複製代碼 代碼如下:
class A{
public:
int operator()(int x){return x;}
};
A a;
a(5);
這樣a就成為一個函數對象,當我們執行a(5)時,實際上就是利用了重載符號()。
函數對象既然是一個“類對象”,那麼我們當然可以在函數形參列表中調用它,它完全可以取代函數指標!如果說指標是C的標誌,類是C++特有的,那麼我們也可以說指標函數和函數對象之間的關係也是同前者一樣的!(雖然有些嚴密)。當我們想在形參列表中調用某個函數時,可以先聲明一個具有這種函數功能的函數對象,然後在形參中使用這個對象,他所作的功能和函數指標所作的功能是相同的,而且更加安全。
下面是一個例子:
複製代碼 代碼如下:
class Func{
public:
int operator() (int a, int b)
{
cout<<a<<'+'<<b<<'='<<a+b<<endl;
return a;
}
};
int addFunc(int a, int b, Func& func)
{
func(a,b);
return a;
}
Func func;
addFunc(1,3,func);
上述例子中首先定義了一個函數對象類,並重載了()操作符,目的是使前兩個參數相加並輸出,然後在addFunc中的形參列表中使用這個類對象,從而實現兩數相加的功能。
如果運用泛型思維來考慮,可以定一個函數模板類,來實現一般類型的資料的相加:
複製代碼 代碼如下:
class FuncT{
public:
template<typename T>
T operator() (T t1, T t2)
{
cout<<t1<<'+'<<t2<<'='<<t1+t2<<endl;
return t1;
}
};
template <typename T>
T addFuncT(T t1, T t2, FuncT& funct)
{
funct(t1,t2);
return t1;
}
FuncT funct;
addFuncT(2,4,funct);
addFuncT(1.4,2.3,funct);
大名鼎鼎的STL中便廣泛的運用了這項技術,詳細內容可參見候捷大師的一些泛型技術的書籍,不要以為函數對象的頻繁調用會使程式效能大大折扣,大量事實和實驗證明,正確使用函數對象的程式要比其他程式效能快很多!所以掌握並熟練運用函數對象才能為我們的程式加分,否則.......
如此看來,函數對象又為C++敞開了一道天窗,但隨之而來的便是一些複雜的問題和陷阱,如何去蔽揚利還需要我們不斷學習和探索。