2011-03-12 51 views
0

我有幾個函數。將幾個回調函數作爲函數參數

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

一個函數whats看起來像那樣。

void setListener(void * listenerCallback); 

我必須發送所有這些函數(a,b,c)作爲「setListener」函數的參數。

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

我該如何做到這一點而不會重載setListener函數?


我找到一個變體。雖然我認爲他可能會造成記憶問題。但事實上,和倫丁解決問題一樣,只有沒有聯盟。

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

請注意,函數指針不一定與數據指針的大小相同。另外,請確保使用某種類型的代碼來確定每個函數具有的參數列表。見倫丁的回答,它同時回答了兩個問題。 –

+0

你在C或C++中執行此操作嗎?每個人都會得到非常非常不同的答案。請注意,C不支持函數重載。另外,在設計回調函數時,通常會強制執行某個函數簽名(或者至少限制可能性)。你想'setListener()'接受任意簽名的函數嗎?或者是否只有'setListener()'將接受的某些函數簽名集? –

+0

爲了什麼是值得的(現在你有幾個工作答案),我不得不說這個設計是有缺陷的,容易出錯和違反直覺。 –

回答

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); 

1020是參數起作用c(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); 

編輯:

(依然,以此爲僞,我還沒有編譯或測試它)

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; 
    } 
    ... 
    } 
} 

編輯2:

順便說一下,應該指出的是,這是唯一的方法在C中一般傳遞幾個函數指針。從一個函數指針到另一個指針類型的野生類型轉換是未定義的行爲。

+0

您可能想要展示如何調用該函數。如果你之前從未使用過類型代碼和聯盟,它可能並不明顯。 –

+0

夠公平,編輯即將到來。 – Lundin

相關問題