関数ポインタの配列を使用する利点は何ですか?Cの関数プロトタイプの数を減らす以外に。
4 に答える
多くの人が指摘しているように、関数ポインタを使用して、Cでオブジェクト指向プログラミングをエミュレートできます。
たとえば、適切なメソッド(別名仮想メソッド)の選択は、単純なインデックス作成を使用して行うことができます。
#include <stdio.h>
#include <stdlib.h>
typedef void (*menu_function_t)();
void menu_error()
{
printf("Invalid menu choice\n");
}
void menu_exit()
{
exit(0);
}
void menu_function1()
{
printf("You have selected 1\n");
}
void menu_function2()
{
printf("You have selected 2\n");
}
menu_function_t menu_ptr[] = {
menu_function1, menu_function2, menu_exit, menu_error
};
int menu_num = sizeof(menu_ptr) / sizeof(menu_ptr[0]);
int validate_choice(int a)
{
if(a < 0 || a > menu_num - 2) { return 3; }
return a;
}
int main()
{
int choice = 0;
while(1)
{
printf("Choose item: \n");
printf("0) Function 1\n");
printf("1) Function 2\n");
printf("2) Exit\n");
scanf("%d", &choice);
menu_ptr[ validate_choice(choice) ]();
}
return 0;
}
関数ポインタを保持する配列(または他のデータ構造)にはさまざまなユースケースがあります。一般に、このタイプのメカニズムにより、プログラムは実行時の基準に基づいていくつかの異なる関数の1つを動的に呼び出すことができます。
たとえば、関数ポインタの配列を使用して、オブジェクト指向言語のインターフェイスに似たものを実装できます。配列は、そのインターフェイスの各実装へのポインタを保持します。配列インデックスは、いくつかの基準に基づいて、目的の実装を選択するために使用されます。
数値を操作に関連付けたい場合は、関数ポインターの配列を使用できますが、実際にはマップと呼ばれます。switch
それは大きな声明を持つことを節約するでしょう。
array[CMD_OPEN] = OpenFunction;
array[CMD_CLOSE] = CloseFunction;
等
void HandleCommand(int aCommand)
{
array[aCommand]();
}
1つの例(多く存在します)は、一連の変数「メソッド」を実装する場合です。
typedef struct tag_IMAGEFORMAT
{
struct tag_IMAGEFORMAT *next;
const char *name;
IMAGEDETECTOR *detect_routine;
int (*open_routine) (DISKIMAGE *img, diskimgflags_t flags);
size_t (*read_routine) (DISKIMAGE *img);
int (*close_routine) (DISKIMAGE *img);
} IMAGEFORMAT;
Cでのオブジェクト指向プログラミング。次に、たとえばを呼び出します。object->open_routine(..)
この例では、実行時に実装を動的に変更できます(この例では、画像形式によって異なります)。
この例では、いくつかの画像形式が共通のAPIを共有しています。さまざまな「検出器」が次々に実行され、最初に一致したものがそのポインタを「一般的な画像」オブジェクトにコピーします。その後、実装の詳細(JPG、GIF、PNGなど)を気にせずに画像を操作できます。
同様に、関数のいくつかの異なるバリエーション(たとえば、画像フィルター)を実装する必要がある場合は、すべてのポインターを配列に保持し、配列へのインデックスを介して適切なポインターを選択できます。