コールバック関数の本質-コールバック関数とは何か、なぜコールバック関数を使用するのか

3152 ワード

C/C++では、関数の概念がよく理解されています.あるタスクを独立してパッケージ化し、パラメータと戻り値を付けることができます.では、コールバック関数は何ですか.関数と何が違うの?すでに関数がある以上、なぜコールバック関数を作らなければならないのですか.きっと、仲間たちはこの概念に出会ったばかりの頃、これらの問題に悩まされていたに違いない.ネットで検索すると、関連資料がたくさんありますが、必ずしも透徹しているとは限りません.私は本当に1つの概念を理解するには、まずその存在の意味を理解しなければならないと思います.つまり、それがなぜ存在するのか、それがどんな便利さをもたらすのかを理解しなければなりません.この点ではC++Primerという本がきちんと書かれています.よく読んでから、自分の心得を書いて、皆さんの参考にします.
まず、コールバック関数も関数で、白馬も馬のようです.パラメータと戻り値を持つ関数のすべてのフィーチャーがあります.実際には,1つの関数を単独で与えると,それがコールバック関数であるかどうかは見えない.コールバック関数は、通常の関数とは異なり、その呼び出し方法にあります.ある関数(より正確には関数のポインタ)がパラメータとして、別の関数によって呼び出される場合にのみ、コールバック関数です.ご飯を1杯あげるように、昼ご飯なのか晩ご飯なのかは言えませんが、ある時にそれを食べてから、昼ご飯なのか晩ご飯なのかを明らかにします(この比喩は少し挫折しているようです.精神を理解すればいいです.ハハ).
では、問題が来ました.なぜ関数をパラメータとして呼び出すのか、直接関数体の中で呼び出すのはよくありませんか.この問題はよく聞きました.この意味で、「関数をパラメータにする」と「変数をパラメータにする」の目的は一致し、不変で変化することである.形パラメータは不変であり,実パラメータは変化する.唯一の違いは、普通の実パラメータはコンピュータプログラムによって自動的に生成されますが、関数というパラメータのコンピュータプログラムは自分で書くことができません.関数自体がプログラムです(プログラムがプログラムを書くことができればスーパー人工知能です)、それは人によって書かなければなりません.したがって、コールバック関数というパラメータにとって、その「変化」は、人が変化しているか、人のニーズが変化しているかにある.
C++Primerでは、ソートアルゴリズムの例を挙げています.ソートアルゴリズムを異なるタイプのデータに適応させ、かつ様々な要求に従ってソートすることができるようにするために、機知に富んだ人間はソートアルゴリズムを1つのテンプレート(標準テンプレートライブラリSTLにおいて)にし、さらに,2つのデータ間の「サイズ」(バイト数,あるいは他の比較可能な属性)を判断するタスク(すなわち関数)を1つのパラメータとしてソートアルゴリズムという関数のパラメータリストに入れ,その具体的な実装をソートアルゴリズムを用いた人に渡した.この大きさを判断する関数はコールバック関数です.たとえば、vectorコンテナ内の単語をソートすると、ソートアルゴリズムを宣言できます.
void stable_sort(vector::iterator iterBegin, vector::iterator iterEnd, 
bool (*isShorter)(const string &, const string &));

前の2つは通常のパラメータ、すなわち反復器(vectorコンテナ内の要素の位置をマークするために使用される)であり、3番目のパラメータisShorterはコールバック関数である.必要に応じてisShorterは、関数名を含む異なる実装を行うことができる.例:
bool myIsShorter(const string &s1, const string &s2)
{    
     return s1.size()
必要に応じて、別の方法で実現することもできます.なお、myIsShorterというパラメータを渡す場合は、関数ポインタを表す関数名を書くだけです.后ろは绝対に()とパラメータをプラスすることができなくて、绝対に()とパラメータをプラスすることができなくて、绝対に()とパラメータをプラスすることができません!それは呼び出し関数の戻り値だから!両者は雲泥の差だ!stable_sort実行時,2つの単語の長さを比較する必要がある場合にmyIsShorterを呼び出し,1つの判断を得る.呼び出し時には、isShorter呼び出しのために2つの単語をisShorterに渡す必要があります.だからstable_sortはmyIsShorterを呼び出し、myIsShorterはstable_を呼び出した.sortが与えた単語.相互に呼び出されます.これが「コールバック」という二つの字の意味です!
形パラメータは変わらないが、実パラメータは可変で、不変で変化しなければならない.しかし,実パラメータとしては,実パラメータのデータ型が変わらない点がある.例えばvoid foo(int i)という関数のパラメータiは1でも2でもよいが,整数でなければならない.同様に,コールバック関数というパラメータのタイプも変えられない.関数のタイプは、関数のパラメータタイプと戻り値タイプによって決まります.たとえば、前述のソートアルゴリズムでは、isShorterというコールバック関数のパラメータは2つのconst stringタイプでなければなりません.戻り値はboolタイプでなければなりません.したがって,コールバック関数を書く際にはあまりわがままを言ってはいけないので,コールバック関数を呼び出す関数の宣言を確認しなければならない.ここに広告を挿入する.コールバック関数には2つのパラメータしかないはずですが、もっと適切にしたいので、3つのパラメータを伝えたいのですが、どうすればいいですか.この問題を解決するために,C++標準委員会はまたlambda式とbind関数の2つの方法を発明した.詳細はこちらとこちらを押してください.
要するに,コールバック関数とは関数をパラメータとして用いることである.プログラムをより適切にすることを目的としています(活字印刷のように、「変」する可能性のある字を一つ一つ分離し、任意に組み合わせて、繰り返し利用することができます).一般的には、ゲームエンジンなどのツールボックスにして他の人に使用されない限り、一人の小規模なプログラムではこのような普遍性は必要ありません.このような汎用性を実現するには、虚関数を書き換える(または純虚関数を用いる.Objective Cのすべての関数は虚関数であり、プロトコルは純虚関数に相当する).これにより、同じ関数で異なる実装が可能になります.このような虚関数「プロトコル」によって、異なる協力者間で協力することができます.
レベルが限られていて、もし妥当でないならば、レンガを撮ることを歓迎します!
参考文献
C++ Primer