1. 程式人生 > >回撥函式(二)

回撥函式(二)

回撥函式作用:

對於很多初學者來說,往往覺得回撥函式很神祕,很想知道回撥函式的工作原理。本文將要解釋什麼是回撥函式、它們有什麼好處、為什麼要使用它們等等問題,在開始之前,假設你已經熟知了函式指標。

(1)什麼是回撥函式? 簡而言之,回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用為呼叫它所指向的函式時,我們就說這是回撥函式。 (2)為什麼要使用回撥函式? 因為可以把呼叫者與被呼叫者分開。呼叫者不關心誰是被呼叫者,所有它需知道的,只是存在一個具有某種特定原型、某些限制條件(如返回值為int)的被呼叫函式。 如果想知道回撥函式在實際中有什麼作用,先假設有這樣一種情況,我們要編寫一個庫,它提供了某些排序演算法的實現,如氣泡排序、快速排序、shell排序、shake排序等等,但為使庫更加通用,不想在函式中嵌入排序邏輯,而讓使用者來實現相應的邏輯;或者,想讓庫可用於多種資料型別(int、float、string),此時,該怎麼辦呢?可以使用函式指標,並進行回撥。 回撥可用於通知機制,例如,有時要在程式中設定一個計時器,每到一定時間,程式會得到相應的通知,但通知機制的實現者對我們的程式一無所知。而此時,就需有一個特定原型的函式指標,用這個指標來進行回撥,來通知我們的程式事件已經發生。實際上,SetTimer()API使用了一個回撥函式來通知計時器,而且,萬一沒有提供回撥函式,它還會把一個訊息發往程式的訊息佇列。 另一個使用回撥機制的API函式是EnumWindow(),它列舉螢幕上所有的頂層視窗,為每個視窗呼叫一個程式提供的函式,並傳遞視窗的處理程式。如果被呼叫者返回一個值,就繼續進行迭代,否則,退出。EnumWindow()並不關心被呼叫者在何處,也不關心被呼叫者用它傳遞的處理程式做了什麼,它只關心返回值,因為基於返回值,它將繼續執行或退出。 不管怎麼說,回撥函式是繼續自C語言的,因而,在C++中,應只在與C程式碼建立介面,或與已有的回撥介面打交道時,才使用回撥函式。除了上述情況,在C++中應使用虛擬方法或函式符(functor),而不是回撥函式。

回撥函式例子:


#include<stdio.h>

// 方法指標的格式為:int (*ptr)(char *p) 即:返回值(指標名)(引數列表)
typedef int (*CallBackFun)(char *p); // 為回撥函式命名,型別命名為 CallBackFun,引數為char *p

int Afun(char *p) {    // 方法 Afun,格式符合 CallBackFun 的格式,因此可以看作是一個 CallBackFun
    printf("Afun 回撥打印出字元%s!\n", p);
    return 0;
}

int Cfun(char *p) {    // 方法 Bfun,格式符合 CallBackFun 的格式,因此可以看作是一個 CallBackFun
    printf("Cfun 回撥列印:%s, Nice to meet you!\n", p);
    return 0;
}

int call(CallBackFun pCallBack, char *p) { // 執行回撥函式,方式一:通過命名方式
    printf("call 直接打印出字元%s!\n", p);
    pCallBack(p);
    return 0;
}

// int call2(char *p, int (*ptr)(char *p)) 
int call2(char *p, int (*ptr)()) { // 執行回撥函式,方式二:直接通過方法指標
    printf("==============\n", p); 
    (*ptr)(p); 
}

int call3(char *p, CallBackFun pCallBack){ // 執行回撥函式,方式一:通過命名方式
    printf("--------------\n", p);
    pCallBack(p); 
}

int main() {    

    char *p = "hello";

    call(Afun, p);
    call(Cfun, p);

    call2(p, Afun);
    call2(p, Cfun);

    call3(p, Afun);
    call3(p, Cfun);

    // int i = getchar();
    // printf("Input: %c \n", i);

    return 0;
}

Linux下的編譯、輸出:

[[email protected] src]$ gcc -o func_callback func_callback.c
[[email protected] src]$ ./func_callback
call 直接打印出字元hello!
Afun 回撥打印出字元hello!
call 直接打印出字元hello!
Cfun 回撥列印:hello, Nice to meet you!
==============
Afun 回撥打印出字元hello!
==============
Cfun 回撥列印:hello, Nice to meet you!
--------------
Afun 回撥打印出字元hello!
--------------
Cfun 回撥列印:hello, Nice to meet you!
[[email protected] src]$

相關推薦

JavaScript使用函式

AJAX - onreadystatechange 事件 菜鳥教程地址http://www.runoob.com/ajax/ajax-xmlhttprequest-onreadystatechange.html/*不使用回撥函式*/<!DOCTYPE html&g

【FreeRTOS】小白進階之任務如何共用FreeRTOS軟體定時器函式

介紹兩個定時器任務如何通過定時器 handle 共用一個回撥函式。 1、標頭檔案宣告和函式定義 #include "FreeRTOS.h" #include "task.h" #include "t

函式

回撥函式作用: 對於很多初學者來說,往往覺得回撥函式很神祕,很想知道回撥函式的工作原理。本文將要解釋什麼是回撥函式、它們有什麼好處、為什麼要使用它們等等問題,在開始之前,假設你已經熟知了函式指標。 (1)什麼是回撥函式? 簡而言之,回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引

函式

#include<stdio.h> // 方法指標的格式為:int(*ptr)(char *p) 即:返回值(指標名)(引數列表) typedefint (*CallBackFun)(char *p); // 為回撥函式命名,型別命名為 CallBackFun

WebService、Ajax與函式

       本例項演示藉助WebService、Ajax技術和回撥函式,從MSSQL資料庫中獲取所需資料,並用JavaScript語言將資料結果顯示到網頁地圖上。 1、WebService        (1)在工具箱的Ajax Extentions下面找到ScriptM

淺談C/C++函式Callback& 函式指標

摘要:回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。

JS之函式callback

1.什麼是回撥函式?   -- 簡單點說,一個函式被作為引數傳遞給另一個函式(在這裡我們把另一個函式叫做“otherFunction”),回撥函式在otherFunction中被呼叫。   --可以是匿名函式也可以是命名函式 2.回撥函式的特點   (1)自己定義的函式   (2)你沒有呼叫   (

JavaScript基礎總結深入資料型別、資料_變數_記憶體、物件、函式函式、this

資料型別 1、分類 JavaScript 資料型別分為兩大類,分別為:基本型別,又稱為值型別;物件型別,又稱為引用型別。 基本(值)型別 String:任意字元 Number:任意的數字 boolean: true/false undefined: undefi

深入淺出函式知乎上看到最好的回答

回撥方法介紹之中國好室友篇(Java示例)前言在Java社群的各種開源工具中,回撥方法的使用俯拾即是。所以熟悉回撥方法無疑能加速自己對開源輪子的掌握。網上搜了一些文章,奈何對回撥方法的介紹大多隻停留在什麼是回撥方法的程度上。本篇文章嘗試從回撥方法怎麼來的、為什麼要使用回撥方法以及在實際專案中如何使用等方面來介

將類的成員函式作為函式外一篇:友元函式

問題的提出  我們已知道類具有封裝和資訊隱藏的特性。只有類的成員函式才能訪問類的私有成員,程式中的其他函式是無法訪問私有成員的。非成員函式可以訪問類中的公有成員,但是如果將資料成員都定義為公有的,這又破壞了隱藏的特性。另外,應該看到在某些情況下,特別是在對某些成員函式多次呼叫時,由於引數傳遞,型別檢查和安全性

ajax的函式done,fail,always

直接上程式碼 <!DOCTYPE html> <html> <head>     <meta charset="utf-8"><title>ajax</title><script type="te

Java 函式傳統方法和lambda方法-一個例子秒懂

背景: 想寫一個工具類 Tool.java ,其中方法 public void readOneLine() 負責一行一行地讀檔案,然後根據不同的業務,對每一行進行不同處理。最後輸出到檔案 out.txt 那麼問題來了,根據不同的業務,進行不同處理 怎麼實現?

ROS 類內如何使用成員函式作為subscribe的函式this指標

ros::Subscriber sub = n.subscribe("chatter", 1000, &Listener::callback, &listener); 使用類內函式時,將第四個引數替換成this: ros::Subscriber sub

學JS的心路歷程-函式arguments

引數(argument)與函式引數(parameter) 在討論函式時,很多人都會把這兩個搞混,我自己也不例外。 雖然講錯別人也聽得懂,但是我們還是要搞清楚這兩個的定義到底是什麼!   引數是當我們呼叫函式時傳遞給它的值 引數是我們在函式定義中所列出的變數看完還是有點不懂?沒關係,上圖!

JS中函式一)

一.前奏 多用在使用 js 寫元件時,尤其是元件的事件很多都需要回調函式的支援 假設   A是回撥函式,B是呼叫者,B引數裡一個是指向A的函式指標,即回撥A,同時另外的引數傳遞給A作為引數 二.JS中函式可作為引數傳遞,甚至在另一個函式內部返回 一旦作為引數

字元驅動裝置原理及其相關函式

參看朱有鵬老師嵌入式視屏,第五部分第三章 1、(1)老介面:register_chrdev (2)新介面:register_chrdev_region/alloc_chrdev_region + cdev register_chrdev_region/alloc_chrdev_regio

JS之函式

函式講解二    1、JS三部曲          語義分析、預編譯、解釋執行    2、預編譯詳解      

Spark Streaming狀態管理函式——updateStateByKey的使用scala版

updateStateByKey的使用   關於updateStateByKey   注意事項   示例程式碼   執行   結論 關於updateStateByKey   1.重點:首先會以DStream中的資料進行按key做reduce操作,然

C++學習筆記——建構函式

委託建構函式:使用類的其他建構函式執行初始化過程 Clock(int newH, int newM, int newS): hour(newH), minute(newM), second(newS){ } Clock:Clock(0,0,0){} //無參建構函式呼叫有參建構函式,將預設初始化

day 16 - 1 內建函式

內建函式(二) reversed()  返回一個反向的迭代器 k = [1,2,3,4,5] k.reverse() #反轉 print(k) k = [1,2,3,4,5] k2 = reversed(k) #反向的迭代器 print(k2) for i in k2: pri