1. 関数ポインタ
関数ポインタ: 関数空間の先頭アドレスを指すポインタ変数。
関数ポインタは次のように定義されます。
関数戻り値の型(*ポインタ変数名)(関数パラメータリスト);
通常、使いやすさを考慮して、
typedef関数の戻り値の型(*ポインタ変数名)(関数パラメータリスト);
typedef の機能は、新しい型を定義することです。
-
// 関数ポインタ
-
タイプ
int
(*ptrFunc)(
int
、
int
);
最初の文では ptrFunc の型を定義し、この型を特定の関数へのポインタとして定義しています。この関数は 2 つの int をパラメータとして受け取り、int 型を返します。後で、int や char などの変数型名を使用するのと同じように ptrFunc を使用できます。
2.コールバック関数と登録関数
簡単に言うと、登録された関数が親関数であり、登録された関数が子関数です。親関数は、実行する子関数を指定できます。次のコードを見てください。
ここでは 4 つのコールバック関数を作成しました。それらの関数シグネチャは前に定義した関数ポインタと一致していますが、異なる関数を完成させます。次に、登録関数を作成します。関数のパラメータは、ptrFunc 型の関数ポインタと、int 型の 2 つのパラメータです。この関数ポインターを通じて、同じ関数シグネチャの 4 つのコールバック関数を登録された関数に与えることができ、次の 2 つの int パラメーターはコールバック関数によってのみ使用されます。
したがって、main 関数には次のようになります。
登録関数は 4 つのコールバック関数を呼び出し、出力結果は次のとおりです。
それが私たちが望んでいる結果です。
ただし、この例はコールバック関数を登録する魔法を反映していません。
3. C言語はコールバック関数を通じてポリモーフィズムを実装します。
先ほどの例と同じですが、この出力関数を完成させたいのであれば、この4つの計算関数をmain関数内で直接呼び出した方が良いのではないでしょうか?似ている:
-
追加(a, b);
-
-
サブ
(a, b);
-
...
このコードは少なくて理解しやすいですが、登録関数 register を使用して 4 つのコールバック関数 (add、sub、mul、div) を一度に複数回呼び出す必要があるようです。
ポリモーフィズムを実現するには、レジスタ パラメータを構造体にカプセル化します。次のように変更します。
まず、関数ポインタの下に構造体を作成し、その構造体のデータには 2 つの int と関数ポインタが含まれます。この関数ポインターを関数マネージャーと呼びます。
ここで登録関数に渡すのは、3 つのパラメーターではなく、これら 3 つのパラメーターをパッケージ化した構造です。
main 関数で呼び出すと次のようになります。
Register 関数のパラメーターは変更されていませんが、すべて my_data であることがわかります。
Register(my_data);
ただし、function managerの値を変更することで、 Register(my_data) の出力を変更できます。
これにより、C言語におけるポリモーフィズムが実現されます。
オブジェクト指向ポリモーフィズムの実装原理は同じです。