2011-03-12 16 views
0

私はいくつかの関数を持っています。複数のコールバックを関数パラメータとして投稿する

void a(); 
bool b(); 
void c(int x, int y); 

1つの機能はそれに似ています。

void setListener(void * listenerCallback); 

この関数(a、b、c)をすべて "setListener"関数のパラメータとして送信する必要があります。

setListener(&a); 
setListener(&b); 
setListener(&c); 

これを行うには、setListener関数をオーバーロードしないでください。


私は1つの亜種を見つける。私は彼が記憶に問題を引き起こしているかもしれないと思うが。しかし実際には、それはLundinの解法と同じであり、組合がない場合のみです。

typedef unsigned int varCallback; 

enum callbackType { 
    C_VOID, 
    C_BOOL, 
    C_VOID_INT_INT, 
} 

void setListener(varCallback callbackPointerAddress, callbackType type) { 
    /// code 
} 

void a() {}; 
bool b() {}; 
void c(int x, int y) {}; 

setListener((varCallback)&a, C_VOID); 
setListener((varCallback)&b, C_BOOL); 
setListener((varCallback)&c, C_VOID_INT_INT); 
+1

関数ポインタはデータポインタと同じサイズである必要はないことに注意してください。また、ある種のコードを使用して、各関数がどのような引数リストを持っているかを確認してください。 Lundinの答えを参照してください、それはすぐに問題の両方に答える。 –

+0

CやC++でこれをやっていますか?それぞれに非常に異なる回答が得られます。 Cは関数の多重定義をサポートしていないことに注意してください。また、コールバックを設計するときには、通常、特定の関数シグネチャを適用します(または、可能性を制限する)。 'setListener()'が任意の署名の関数を受け入れるようにしますか?あるいは、 'setListener()'が受け入れる特定の関数シグネチャのセットしかありませんか? –

+0

これは価値があります(今、あなたは2つの作業の答えがあります)。この設計には欠陥があり、誤りが多く、直観に反しやすいと言わなければなりません。 –

答えて

0

関数テンプレートと関数を書くことができます。

例:

void a(); 
bool b(); 
void c(int x, int y); 

template<typename Fun> 
void setListener(Fun listenerCallback); 

template<typename Fun, typename TArg1, typename TAgr2, typename R> 
struct Functor 
{ 
    Fun m_fun; 
    TArg1 m_arg1; 
    TArg2 m_arg2; 
    Functor(Fun fun, TArg1 arg1, TArg2 arg2) 
     : m_fun(fun), m_arg1(arg1), m_arg2(arg2) {} 
    R operator()() 
    { 
     return m_fun(arg1, arg2); 
    } 
}; 

Functor<void (*)(int,int), int, int, void> c_fun(c, 10, 20); 

setListener(&a); 
setListener(&b); 
setListener(c_fun); 

1020c(int, int)を関数の引数です。

注:これはあまり一般的な解決策ではありませんが、これはここで尋ねられる問題に固有です。

+0

あなたのコードで 'a'とは何ですか?それはどこから来たのですか? –

+0

@AndréCaron:「a」は、OPのコードスニペットの 'void a()'関数を指していると思います。 –

+0

@Andre:それは機能です。最初の質問を参照してください! – Nawaz

2

あなたはこのCをタグ付けしたように、ここで(擬似コードなどについて)だけでなくCのソリューションです:

typedef enum 
{ 
    FPTR_VOID_VOID, 
    FPTR_BOOL_VOID, 
    FPTR_VOID_INT_INT 
} Func_ptr_t; 

typedef struct 
{ 
    Func_ptr_t type; 

    union 
    { 
    void(*void_void)(); 
    bool(*bool_void)(); 
    void(*void_int_int)(int, int); 
    }; 
} My_func_ptr_t; 


My_func_ptr_t var = {FPTR_VOID_VOID, &a}; 
setListener(&var); 

EDIT:

(まだ、擬似などについては、これは、私がコンパイルされていませんか、

void setListener (void * listenerCallback) 
{ 
    const My_func_ptr_t* func_ptr; 

    func_ptr = (const My_func_ptr_t*) listenerCallback; 

    switch(func_ptr->type) 
    { 
    case FPTR_VOID_VOID: 
    { 
     func_ptr->void_void(); 
     break; 
    } 
    ... 
    } 
} 

EDIT 2)それをテスト:ところで、これが唯一の方法であることに留意すべきである

ある関数ポインタから別のポインタ型への野生型の型キャストは未定義の振る舞いです。

+0

関数を呼び出す方法も示したい場合があります。これまでに型コードと共用体で作業したことがない人は、明らかではないかもしれません。 –

+0

十分に公正な編集が行われます。 – Lundin

関連する問題