私は実用的なシナリオで関数ポインタが使用されているかを理解しようとしています。 誰も私に関数自体を別の関数の引数として渡す必要がある実用的な例を教えてください。
答えて
ファンクションポインタは、callback mechanismを作成するときに便利であり、関数のアドレスを別の関数に渡す必要があります。
これらは、関数の配列を格納したり、たとえば動的に呼び出したりする場合にも便利です。
一般的な使用方法の1つはcallback functionです。
qsort
ライブラリ機能を使用して並べ替えを試みます。最後のパラメータは、あなたが書いたコンパレータ関数へのポインタです。
非常に便利なアプリケーションとして私の頭に浮かぶのはボタンです。次のコードを取る:
int buttonID = CreateButton ("Click Me!", 100, 100, 200, 100, onClick);
これは、幅200、高さ100あなたがそれをクリックするたびに付き(100100)のボタンを作成し、onClickのが呼び出されます。
私は個人的なWindows APIラッパーで同様のものを使用します。それはボタンなどを作成するのがずっと簡単になります。
まあ、#1ストックの回答はqsort
です。 qsort
が使用する比較ルーチンは、関数ポインタとして渡されます。他の多くの「ジェネリックアルゴリズム」関数も同様の方法でコンパレータを使用します。例えばおそらくハッシュテーブルの実装があなたのハッシュ関数を受け入れるかもしれません。
C言語のGUIツールキットおよびアプリケーションフレームワーク(Gnome/Gtk +/Glibなど)は、関数呼び出しをタイマまたはユーザーインターフェイスイベントの「コールバック」として受け入れることがよくあります。 (EG:「このボタンがクリックされるたびにこの関数を呼び出す」または「...このタイマーが満了するたびに...」)
実際、Cのほとんどの「OOPのような」または「イベント駆動」のコードは、同様の理由。
関数ポインタのための2つの主要な用途があります。
- コールバック - イベントハンドラのために使用され、パーサー専門、コンパレータ機能通過...
- プラグインやエクステンション - プラグインが提供する関数へのポインタまたはライブラリ拡張は、標準機能(
GetProcAddress
、dlsym
など)によって集められます。これらは、関数識別子を名前として受け取り、関数ポインタを返します。 OpenGLのようなAPIにとって絶対に重要です。
コールバックを関数に渡すために使用できます。たとえば、qsort()
を使用して配列を並べ替えることができます。この機能は、独自のソート順序を使用できることを意味し、その引数の1つとして比較関数を取ります。ほとんどの場合、
// All odd numbers are before even numbers
int cmpoddeven(const void *xp, const void *yp) {
int x = *((int*) xp);
int y = *((int*) yp);
if(x == y)
return 0;
if(x % 2 == y % 2) {
return (x < y ? -1 : 1);
if(x % 2 == 1)
return -1;
return 1;
}
int main() {
int array[] = {1, 2, 3, 4, 5};
// calling qsort with cmpoddeven as the comparison function
qsort(array, 5, sizeof(int), &cmpoddeven);
// array == {1, 3, 5, 2, 4};
}
が、それは本質的dependency inversionを行うためのCの方法です。 wikiの記事には、
と記載されています。下位レベルのモジュールに依存しないでください。どちらも抽象に依存するはずです。 B.抽象は細部に依存すべきではありません。詳細は抽象化に依存する必要があります。
古典的な例のqsort
は、上位レベルのソート機能が、ソート対象のデータの型、サイズ、または比較方法に依存しないという意味でこれを行います。したがって、qsort()
のint配列の場合、詳細はsizeof(int)
と比較の実装です。抽象化は、任意のサイズの要素の配列と、その型の要素を比較する関数です。
例としてpthread_create()
を誰も言及していないことに私は驚いています。
私が考えることができる唯一の一般的な使用方法は、依存性反転として一般化することはできませんが、切り替え不可能なデータ型ではスイッチ状のフロー制御を実装しています。たとえば、文字列をオンにしたい場合は、ソートされた文字列キーを関数ポインタにマッピングしてバイナリ検索を行います。それはスイッチのようなO(1)ではなく、あなたがマッチを見つけるまで、盲目的にstrcmp()を大きなif-elseでやっているよりも優れています。しかし、文字列をトークン化して実際のスイッチを使用するよりも優れているとは限りません。
コールバックルーチンは、これまで説明した最も一般的なシナリオのようです。しかし、多くの他のものがあります...
有限状態マシン(多次元)配列の要素は、次の状態を処理/処理するルーチンを示します。これにより、FSMの定義が1つの場所(配列)に保持されます。
有効化機能と機能の無効化は、関数ポインタを使用して行うことができます。あなたは、同じまたは別個のことをする機能を有効または無効にしたい場合があります。 if-elseを使用してコードを入力および乱雑にする代わりに、関数ポインタを使用するようにコードを作成し、関数ポインタを変更または割り当てて機能を有効または無効にすることができます。新しいバリアントを追加すると、if-elseまたはスイッチのすべてのケースを追跡する必要がなくなり、リスクケースがなくなる危険性もありません。新しい機能を有効にするために関数ポインタを更新するか、古い機能を無効にするだけです。
コードクラッタを減らす私は前の例でこれに触れました。例のような...
switch (a) {
case 0:
func0();
break;
case 1:
func1();
break;
case 2:
func2();
break;
case 3:
func3();
break;
default:
funcX();
break;
}
は多くがよりありへ...
/* This declaration may be off a little, but I am after the essence of the idea */
void (*funcArray)(void)[] = {func0, func1, func2, func3, funcX};
... appropriate bounds checking on 'a' ...
funcArray[a]();
を簡略化することができます。お役に立てれば。
FWIW、宣言'void(* funcArray [])(void)= {func0、func1、func2 ...でなければなりません}; '(' funcArray'は関数へのポインタの配列です...)。宣言が使用を模倣していることを忘れないでくださいコード内の式が 'funcArray [a]()'である場合、宣言は同じように構造化されます。 –
@JohnBode - 非常に感謝しています。私はC言語で20年以上働いていますが、私はまだ関数ポインタの構文が混ざっています。通常は、関数ポインタを最初にtypedef'ingしてからtypedef'ed変数の配列を宣言する方が簡単です(私にとって)。 – Sparky
@ Sparky typedefについて合意しました。これは、関数ポインタの配列や関数ポインタへのポインタのような状況を読みやすくする。 –
- 1. 仮想関数とポインタの使い方を理解する
- 2. Cの構造体で関数ポインタを使う方法は?
- 3. 関数へのポインタを返す関数へのポインタを定義する方法
- 4. javascriptの関数へのポインタの使用
- 5. as3関数ポインタ
- 6. 関数ポインタ、デザイン
- 7. 関数ポインタ
- 8. C#関数ポインタ?
- 9. テンプレートメンバ関数ポインタ
- 10. ブーストバインドクラス関数ポインタ
- 11. C#の関数ポインタ
- 12. JScriptの関数ポインタ
- 13. 関数ポインタJavaの
- 14. Cで関数ポインタを返す関数へのポインタの構文
- 15. 関数ポインタのスタック:関数の呼び出し方法?
- 16. 関数への整数ポインタ
- 17. 関数ポインタの引数リスト
- 18. C++:メンバ関数での関数ポインタの使用
- 19. 可変長の関数ポインタにインライン関数またはC++のMACROSを使う方が良い
- 20. C++のメンバ関数への関数ポインタ
- 21. golangは、閉鎖関数ポインタ
- 22. C++の関数ポインタとコールバック関数
- 23. テンプレート関数への関数ポインタ
- 24. メンバ関数関数オブジェクトへのポインタ
- 25. boost :: geometry関数への関数ポインタ
- 26. 関数内でポインタのポインタを使用する正しい方法は何ですか?
- 27. いくつかの関数のポインタ
- 28. 関数ポインタCで
- 29. printf関数とポインタ
- 30. 抽象関数ポインタ
これはC#ですが、C/C++と関数ポインタの実用性についても説明しています:http://stackoverflow.com/questions/667410/the-benefits-of-using-function-pointers – Algorhythm