2012-05-06 20 views
0

私は戻って、このような別の関数の呼び出しで別の関数ポインタを埋め込むされた関数呼び出しを知っている:Cでは、なぜ関数ポインタが関数呼び出しの方が適しているのですか?

関数の宣言:

function_call_back(int x, int y, void (*functonPtr)(int x, char y , struct newStruct* sptr)) 


void func(int x , char y , struct newStruct* sptr1) 
{ 
    //perform Algorithm 1 on x,y ,sptr1 
} 

void func2(int x , char y , struct newStruct* sptr2) 
{ 
    //perform Algorithm 1 on x,y ,sptr2 
} 


void func3(int x , char y , struct newStruct* sptr3) 
{ 
    //perform Algorithm 1 on x,y ,sptr3 
} 

void func4(int x , char y , struct newStruct* sptr4) 
{ 
    //perform Algorithm 1 on x,y ,sptr4 
} 

main() 
{ 
    // function calling 
    function_call_back(23, 2256, func1); 
} 

関数名と等価であるとして、ここでは3番目の引数が、funcです関数ポインタ

ここでfuncは、類似の関数シグネチャの異なるバリエーションで、この行をメインのabに追加することで変更できますfunction_call_backへの呼び出しの前にOVEを:関数名があるよう

typedef void (*fptr)(int int x , char y , struct newStruct* ptr); 

    fptr f1 = func2; // or func3, or func4 

    function_call_back(23, 2256, f1); 

3番目の引数は、funcですが、私はこれを思っていただけでの呼び出しで関数を呼び出すコードを追加することによって、また、下記の方法で達成することができますfunction_call_back

function_call_back(23, 2256, functionCallingcode); //third argument is func 

function_call_backの新しい宣言は次のとおりです。

function_call_back(int x, int y, int functionCallingCode) 

とその北東定義は次のとおりです。

void function_call_back(int x, int y, int functionCallingCode) 
{ 
switch(functionCallingCode) 
case 1: 
func1(1,"g",sptr1); 
break; 

case 2: 
func2(1,"c",sptr2); 

break 

case 3: 
func3(1,"d",sptr3); 
break; 

case 4 : 
func4(1,"s",sptr4); 
break ; 

default : 
printf("Wrong Function calling code"); 

} 
} 

なぜ関数ポインタを使用するのですか?

+5

何よりも適していますか?あなたのより良い選択肢は何ですか?このコードは読めない混乱です。 – duffymo

+1

あなたはなぜこのような醜い 'スイッチ'をやろうとしますか? – SLaks

+0

@duffymo非関数ポインタの実装よりも適しています。コードをクリアしてクリーンアップします。 – Raulp

答えて

3

switch文を使用すると、のコールバック関数にコード化する関数ごとにを呼び出すことができます。既知の関数コレクションのうちの1つだけが呼び出せることが保証されています。

関数は、後で完全に無関係に定義することができます。一致するシグネチャを持つコールバック関数を自由に定義して使用することができます。

言い換えれば、スイッチを使用すると、限られた範囲の選択肢の中で分岐することができますが、ファンクションポインタは無限の柔軟性を提供します。通常、関数ポインタよりも何かを好む理由はほとんどありません。

3

これらは優れているわけではありませんが、実際には唯一の選択肢です。

このスイッチを使用できますが、同じアプローチでは、1つの機能でプログラム全体を書き込むことができます。機能は、コードユニットを分離するためにあり、この "スイッチ機能"は単なるユニットの数が多すぎます。

2

あなたが説明した場合、関数ポインタを使用せずに必要な機能を明確に得ることができます。

しかし、func5のオプションを数週間で追加する場合はどうなるか考えてみてください。そして、時間が経つにつれて、func6、func7、...、func10、func20を追加したいと思います。 function_call_back()は大きくなっていますが、関数ポインタバージョンでは、function_call_back()をまったく編集することなく、必要なだけ多くの関数を追加できます。

関数ポインタの実装では、あなたや他の誰かが別のプログラムでソースコードを混乱させることなく、または持っていなくても、function_call_back()をライブラリの一部として扱うことができます。なぜこれが本当に便利かの例については、標準ライブラリqsort関数を参照してください。

+2

もっと良い例は次のようなものです:ライブラリ(UIライブラリなど)を書くときに何が起こるかを考え、そのライブラリを使用するプログラムがコールバックを実行するように指定する場合。ボタンがクリックされたとき。 – ninjalj

関連する問題