1. 程式人生 > >回撥函式、函式指標和函式物件

回撥函式、函式指標和函式物件

  對於回撥函式的編寫始終是寫特殊處理功能程式時用到的技巧之一。先介紹一下回調的使用基本方法與原理。

  在這裡設:回撥函式為A()(這是最簡單的情況,不帶引數,但我們應用的實際情況常常很會複雜),使用回撥函式的操作函式為B(), 但B函式是需要引數的,這個引數就是指向函式A的地址變數,這個變數一般就是函式指標。使用方法為:

  int A(char *p); // 回撥函式

  typedef int(*CallBack)(char *p) ; // 宣告CallBack 型別的函式指標

  CallBack myCallBack ; // 宣告函式指標變數

  myCallBack = A; // 得到了函式A的地址  

B函式一般會寫為 B(CallBack lpCall,char * P,........); // 此處省略了p後的引數形式 。

所以回撥機制可理解為,函式B要完成一定功能,但他自己是無法實現全部功能的。 需要藉助於函式A來完成,也就是回撥函式。B的實現為:
B(CallBack lpCall,char *pProvide)
{
........... // B 的自己實現功能語句
lpCall(PpProvide); // 藉助回撥完成的功能 ,也就是A函式來處理的。
........... // B 的自己實現功能語句
}

(1)基於函式指標的回撥函式:

#include < iostream > using namespace  std;

typedef 
int  ( * CallBack)( char * );//定義函式指標,該指標指向引數為 char *返回 int的函式
int  A( char *  str)
{
    cout
<< " function A starts " << endl;
    cout
<< str << endl;
    cout
<< " function A ends " <<
endl;
    
return 0 ;
}
void  B(CallBack call, char *  str)
{
    cout
<< " function B starts " << endl;
    call(str);
    cout
<< " function B ends " << endl;
}

int  main()
{
    
char *  str = " hello,world! " ;
    B(A,str);
    
return 0 ;
}

結果:

function B starts

function A starts

hello,world!

function A ends

function B ends

(2)回撥函式還有另外一種方式:函式物件。

函式物件(也稱“算符”)是過載了“()”操作符的普通類物件。因此從語法上講,函式物件與普通的函式行為類似。

用函式物件代替函式指標有幾個優點:

首先,因為物件可以在內部修改而不用改動外部介面,因此設計更靈活,更富有彈性。函式物件也具備有儲存先前呼叫結果的資料成員。在使用普通函式時需要將先前呼叫的結果儲存在全程或者本地靜態變數中,但是全程或者本地靜態變數有某些我們不願意看到的缺陷。

其次,在函式物件中編譯器能實現內聯呼叫,從而更進一步增強了效能。這在函式指標中幾乎是不可能實現的。

下面的例子說明使用函式指標和函式物件實現整數求負數的的方法。

#include < iostream > using namespace  std;

// 使用函式物件 class  CallBack
{
public :
    
int operator ()( int );
};
int  CallBack:: operator ()( int  arg) //第一個圓括弧總是空的,因為它代表過載的操作符名;第二個圓括弧是引數列表。
{
    
return  ( - arg);
}

int  fun(CallBack call, int  arg) //注意call是物件,而不是函式。
{
    
return  call(arg); //編譯器將語句call(arg)轉化為call.operator()(arg);
}

// 使用函式指標 typedef  int  ( * callback)( int );
int  callfun( int  arg)
{
    
return  ( - arg);
}

int  fun2(callback call, int  arg)
{
    
return  call(arg);
}

int  main()
{
    cout
<< fun(CallBack(), 3 ) << endl;
    cout
<< fun2(callfun, 3 ) << endl;
}

結果:

-3

-3

從上面的例子中可以看出,函式物件資料型別被限制在int,而通用性是函式物件的優勢之一,如何建立具有通用性的函式物件呢?方法是使用模板,也就是將過載的操作符“()”定義為類成員模板,以便函式物件適用於任何資料型別:如double,_int64或char:

#include < iostream > using namespace  std;

// 使用函式物件類模板 template < class  T > class  CallBack2
{
public :
    T 
operator ()(T);
};
template
< class  T >
T CallBack2
< T > :: operator ()(T arg)
{
    
return  ( - arg);
}

int  main()
{
    
// 使用函式物件類模板     cout << CallBack2 < int > ()( 3 ) << endl;
    cout
<< CallBack2 < double > ()( 3.333 ) << endl;    
}

結果:

-3

-3.333

標準庫中函式物件 
C++標準庫定義了幾個有用的函式物件,它們可以被放到STL演算法中。例如,sort()演算法以判斷物件(predicate object)作為其第三個引數。判斷物件是一個返回Boolean型結果的模板化的函式物件。

相關推薦

函式函式指標函式物件

  對於回撥函式的編寫始終是寫特殊處理功能程式時用到的技巧之一。先介紹一下回調的使用基本方法與原理。   在這裡設:回撥函式為A()(這是最簡單的情況,不帶引數,但我們應用的實際情況常常很會複雜),使用回撥函式的操作函式為B(), 但B函式是需要引數的,這個引數就是指向函

函式機制非同步函式機制圖例詳解

函式回撥機制,一種雙向呼叫思想,簡單來說就是,如下圖所示:            在層次一中的方法一(函式)呼叫層次二中的方法,並傳入函式二的地址,而這個被呼叫的方法又會呼叫層次一中的方法,這個最後被

C++複習筆記(六)之函式指標函式模板類模板

一、函式指標 函式指標在C語言中的作用類似於c++中的多型,都是可以實現框架的搭建,程式碼的相容性高。 函式三要素:名稱、引數、返回值 C語言可以通過typedef為函式型別重新命名,語法 typedef  返回值型別(型別名稱)(引數列表);如下程式碼所示: #in

靜態成員函式this指標物件指標動態物件使用小結

·靜態成員函式就是使用static 關鍵字宣告的成員函式  在類外實現時不加static關鍵字,只有在類內宣告時才加static·靜態成員函式是類的一部分,作用是為了處理靜態資料成員  沒有this指標·靜態成員函式可以直接訪問該類的靜態成員,但不能直接訪問類中的非靜態成員·若想在靜態成員fun中使用非靜態成

Day40this指標函式解構函式物件的建立銷燬過程拷貝構造拷貝賦值(深拷貝淺拷貝!)

一、            this和常函式 1、 this 指標 1)     類中的建構函式和成員函式都隱藏一個該類型別的指標引數,引數名為this。 2)     對於普通的成員函式,this指標就是指向呼叫該函式的物件 3)     對於建構函式,this指標指向正

C語言學習筆記(九)—— 函式遞迴指標

一、函式1、一個簡單的函式示例函式是完成特定任務的獨立程式程式碼單元。#include <stdio.h> void printStar();//宣告函式原型,函式原型會指明函式的型別和函式接受的引數。前面的void是函式型別,表明函式沒有返回值 #define

模式對話方塊非模式對話方塊accept()函式exec()函式,Accepted訊號區別

一.非模式對話方塊   非模式對話方塊是和同一個程式中其它視窗操作無關的對話方塊。在字處理軟體中查詢和替換對話方塊通常是非模式的來允許同時與應用程式主視窗和對話方塊進行互動。呼叫show()來顯示非模式對話方塊。show()立即返回,這樣呼叫程式碼中的控制流將會繼續。   非模式

函式指標函式指標型別

參考:https://blog.csdn.net/candyliuxj/article/details/6339414 函式指標 1.     定義 每一個函式都佔用一段記憶體單元,它們有一個起始地址,指向函式入口地址的指標稱為函式指標。

C++函式指標指標函式返回值為函式指標函式淺談

C++函式指標、指標函式、返回值為函式指標的函式淺談 引言 函式指標、指標函式是C中重要而容易混淆的概念,博主將通過兩個例項來說明這兩個截然不同的概念。 而返回值為函式指標的指標函式就更難理解了,放在文章的最後來介紹。 函式指標 函式指標是一種特殊的 指標,它指向函式的入口。

有n個整數,指定位置m處插入g個值(用指標函式

#include <stdio.h> void main() {     void move(int *p,int *s,int n,int m,int g);  int a[30],b[20];     i

c語言的指標陣列陣列指標函式指標

#include <stdio.h> #include <stdlib.h> int func(int x){ return x; } int* func2(int x){ int *p=&x; return

Scala 泛型類泛型函式上邊界 下邊界

泛型類 泛型類:在Scala的類中定義引數型別 泛型類的應用場景:對類中的某些成員(field和method中的引數或變數)進行統一的型別限制,從而確保程式的健壯性和穩定性 class MyCollection[T]{ private val list =new ListBuf

Scala學習筆記(六):本地函式頭等函式佔位符部分應用函式

本地函式 可以在方法內定義方法,這種方法叫本地函式,本地函式可以直接訪問父函式的引數 def parent(x: Int, y: Int): Unit ={ def child(y:Int) = y + 1 val z = child(y) println(s"x: $x, z

tf.nn.conv2d函式padding型別SAMEVALIDtf.nn.max_pool函式tf.nn.dropout函式tf.nn.softmax函式tf.reduce_sum函式

tf.nn.conv2d函式: 該函式是TensorFlow裡面實現卷積的函式。 函式形式: tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None,

一些概念:類結構名稱空間複製建構函式作用域連結性 自動變數堆疊

  1、類和結構       類描述看上去很像是包含成員函式以及public和private可見性標籤的結構宣告。實際上,C++對結構進行了擴充套件,使之具有與類相同的特性。他們之間唯一的區別是,結構的預設訪問型別是public,而類為pri

【虛擬函式虛擬指標虛表指標】解析多重繼承時,虛表的分佈

#include<iostream> using namespace std; //抽象基類:動物類 class CAnimal { public: virtual void EatFood(string strSomething) =

C語言-陣列字元指標陣列函式介面與使用

#include <stdio.h> #include <stdlib.h> typedef char* myString; //#define MY_STRING #if

MySQL聚合函式模糊查詢約束

聚合函式 聚合函式也叫組函式,在一個行的集合(一組行)上進行操作,並對每個組給予一個結果. 常用的聚合函式: AVG:求平均值 COUNT:統計行的數量 MAX:求最大值 MIN:求最小值 SUM

除非同時指定了 TOP,否則 ORDER BY 子句在檢視內嵌函式派生表子查詢中無效。

在sql server 2000中,報錯:”除非同時指定了 TOP,否則 ORDER BY 子句在檢視、內嵌函式、派生表和子查詢中無效。“,如果實在要用 ORDER BY ,但是又不能指定確定的TOP資料時,怎麼辦呢? 解決方案: 使 用 TOP 100 PERCENT (

虛擬函式,虛指標虛表詳解

關於虛擬函式的背景知識 1. 用virtual關鍵字申明的函式叫做虛擬函式,虛擬函式肯定是類的成員函式。 2. 存在虛擬函式的類都有一個一維的虛擬函式表叫做虛表。每一個類的物件都有一個指向虛表開始的虛指標。虛表是和類對應的,虛表指標是和物件對應的