C++中的函數指針和函數對象總結

http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html

篇一、函數指針
函數指針:是指向函數的指針變量,在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++敞開了一道天窗,但隨之而來的便是一些復雜的問題和陷阱,如何去蔽揚利還需要我們不斷學習和探索。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384121.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384121.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384121.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開發工具

1.編輯器 &#xff08;1&#xff09;vim ????vim是從vi發展出來的一個文本編輯器。代碼補完、編譯錯誤跳轉等方便編程的功能特別豐富&#xff0c;在程序員中被廣泛使用。 &#xff08;2&#xff09;sed ????sed是一種流編輯器&#xff0c;它一次處理一行內容。處理時…

575 div3RGB Substring (hard version)——思維-

【題目描述】 The only difference between easy and hard versions is the size of the input. You are given a string s consisting of n characters, each character is ‘R’, ‘G’ or ‘B’. You are also given an integer k . Your task is to change the minimum …

c++ 智能指針用法詳解

http://www.cnblogs.com/TenosDoIt/p/3456704.html 本文介紹c里面的四個智能指針: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三個是c11支持&#xff0c;并且第一個已經被c11棄用。 為什么要使用智能指針&#xff1a;我們知道c的內存管理是讓很多人頭疼的事&#xff0…

CodeForces - 786BLegacy——線段樹建圖+最短路

【題目描述】 CodeForces - 786BLegacy 【題目分析】 題目大概意思就是有三種操作&#xff1a; 從某個點到另一個點從某個點到另一個區間從某個區間到另一個點 然后詢問從其中一個點到其他所有點的距離——這很顯然是一個求單源最短路徑的。我們簡單的想法顯然是建一個圖&a…

自主編寫shell

1.替換原理 用fork創建子進程后執行的是和父進程相同的程序&#xff08;但有可能執行不同的代碼分支&#xff09;&#xff0c;子進程往往要調用一種exec函數以執行例外一個程序。當進程調用一種exec函數時&#xff0c;該進程的用戶空間代碼和數據完全被新程序替換&#xff0c;從…

HYSBZ - 2243染色——樹鏈剖分+線段樹建樹技巧

【題目描述】 HYSBZ - 2243染色 【題目分析】 我一直沒有看清楚題&#xff0c;以為求的是路徑上出現顏色的種類&#xff0c;然后就寫了一個區間染色的線段樹進行維護&#xff0c;過樣例的時候才發現題讀錯了&#xff0c;人家要求的是路徑上出現的顏色段&#xff0c;所以顏色的…

右值引用與轉移語義

https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ 新特性的目的 右值引用 (Rvalue Referene) 是 C 新標準 (C11, 11 代表 2011 年 ) 中引入的新特性 , 它實現了轉移語義 (Move Sementics) 和精確傳遞 (Perfect Forwarding)。它的主要目的有兩個方面&#xff…

打動態庫和靜態庫

一.動態庫和靜態庫的定義 1.靜態庫 ????程序在編譯鏈接時把庫的代碼鏈接到可執行文件中。程序運行時就不再需要靜態庫 2.動態庫 ????程序在運行的時候才去鏈接動態庫的代碼&#xff0c;多個程序 共享使用代碼 3.動態鏈接 ????在執行文件之前&#xff0c;外部…

HYSBZ - 2157樹鏈剖分

【題目描述】 HYSBZ - 2157樹鏈剖分 【題目分析】 這道題給出的是邊權而不是點權&#xff0c;但是我們分析這個樹就會發現每個節點都只有一個父親&#xff0c;也就是每條邊的邊權都可以存放在兒子節點上&#xff0c;然后在遍歷路徑的時候我們在從前往后遍歷&#xff0c;但是注…

C++11中的右值引用

http://www.cnblogs.com/yanqi0124/p/4723698.html 在C98中有左值和右值的概念&#xff0c;不過這兩個概念對于很多程序員并不關心&#xff0c;因為不知道這兩個概念照樣可以寫出好程序。在C11中對右值的概念進行了增強&#xff0c;我個人理解這部分內容是C11引入的特性中最難以…

BZOJ2115XOR——線性基

【題目描述】 BZOJ2115XOR——線性基 【題目分析】 這道題看完以后很懵逼&#xff0c;人家要是走的很復雜呢&#xff1f;各種繞來繞去怎么辦&#xff1f; 首先我們應該注意到一個很明顯的道理&#xff1a;重復的路徑會和自身抵消&#xff0c;所以我們大可以隨便跑&#xff0c;…

單鏈表的相關操作

1.冒泡排序對單鏈表進行排序 void LinkListBubbleSort(LinkNode* head) {if(head NULL){ return;//空鏈表} if(head -> next NULL){ return;//只有一個結點} LinkNode* cur head;//趟數LinkNode* tail NULL;//尾指針LinkNode* tmp head;//次數for(; cur -…

socket網絡編程--epoll小結

http://www.cnblogs.com/wunaozai/p/3895860.html 以前使用的用于I/O多路復用為了方便就使用select函數&#xff0c;但select這個函數是有缺陷的。因為它所支持的并發連接數是有限的(一般小于1024)&#xff0c;因為用戶處理的數組是使用硬編碼的。這個最大值為FD_SETSIZE&#…

進程間通信(匿名管道)

1.進程通信的目的 (1) 數據傳輸: 一個進程需要將它的數據傳輸給另一個進程 ????(2) 資源共享: 多個進程之間共享同樣的資源 ????(3) 通知事件: 一個進程需要向另一個或一組進程發送消息, 通知它們發生了什么事情 2.管道 管道是一種進程之間通信的一種方式, 我們把從…

線性基入門

今天學習了神奇的線性基&#xff0c;主要是在解決異或問題時比較有用。 詳細的解釋和證明有大佬珠玉在前&#xff0c;如果感興趣可以移步 補充一下自己的理解&#xff1a; 可以聯系線性代數極大無關組進行理解&#xff0c;線性基就相當于異或的向量空間中的極大無關組&#xff…

單例模式及C++實現代碼

http://www.cnblogs.com/cxjchen/p/3148582.html 單例模式 單例模式&#xff0c;可以說設計模式中最常應用的一種模式了&#xff0c;據說也是面試官最喜歡的題目。但是如果沒有學過設計模式的人&#xff0c;可能不會想到要去應用單例模式&#xff0c;面對單例模式適用的情況&am…

UVALive - 8512——線段樹維護線性基

【題目描述】 UVALive - 8512XOR 【題目分析】 這種區間線性基的問題我們可以考慮用線段樹維護&#xff0c;線性基的合并的話就直接暴力合并 找到所在區間的線性基后再查找最大的數&#xff0c;我看網上的博客要說消除k的影響什么的&#xff0c;我覺得沒有什么必要&#xff0c;…

命名管道

1.命名管道的創建 (1) 通過命令創建 mkfifo filename (2)在程序中創建 int mkfifo(const char* filename, mode_t mode); 2. 命名管道和匿名管道的區別 (1)匿名管道由pipe函數創建并且打開 ????(2)命名管道有mkfifo函數創建由open函數打開 ????(3) fifo 之間的兩…

HYSBZ - 1101——莫比烏斯反演

【題目描述】 HYSBZ - 1101 【題目分析】 昨天測試出了一道差不多的題目&#xff0c;我只能想到暴力&#xff0c;各種優化&#xff0c;最后都是運行了好久TLE&#xff0c;最后才知道要用到莫比烏斯反演&#xff0c;就想著今天研究一下&#xff0c;得出的結論就是&#xff0c;我…

Linux下I/O多路轉接之select --fd_set

http://blog.csdn.net/li_ning_/article/details/52165993 fd_set 你終于還是來了&#xff0c;能看到這個標題進來的&#xff0c;我想&#xff0c;你一定是和我遇到了一樣的問題&#xff0c;一樣的疑惑&#xff0c;接下來幾個小時&#xff0c;我一定竭盡全力&#xff0c;寫出我…