2011-05-04 73 views
2

有什麼辦法可以在所有動作類型的基本函數中執行代碼?我想執行所有do_card操作通用的行爲。換句話說,我想打印遊戲狀態,但我想避免在每個單獨的do_card函數中重複printf,而是隻寫一次。有沒有辦法在C中實現這一點?C函數裝飾/多態

struct CARD { 
    int value; 
    int cost; 
    // This is a pointer to a function that carries out actions unique 
    // to this card 
    int (*do_actions) (struct GAME_STATE *state, int choice1, int choice2); 
}; 
int do_card0(struct GAME_STATE *state, int choice1, int choice2) 
{ 
    // Operate on state here 
} 

int do_card1(struct GAME_STATE *state, int choice1, int choice2) 
{ 
    // Operate on state here 
} 

static struct cardDefinitions[] = { 
    {0, 1, do_card0}, 
    {1, 3, do_card1} 
}; 
int result = cardDefinitions[cardNumber].do_action(state, choice1, choice2); 
+0

'c'中沒有裝飾器。在調用這些函數之前,可以嘗試使用'printf',如果代碼中可能的話。它看起來像你有一些'if'或'switch'語句 - 如果消息是相同的並且適用於所有函數,請在調用其中的任何函數之前先將其放回 – 2011-05-04 20:58:09

+0

此代碼避免使用目標開關。我希望能夠在所有類型中添加行爲,但我認爲它不可能在C中使用。 – 2011-05-04 21:01:39

+1

您應該嘗試給出更具體的示例。我不確定你想在這裏避免什麼樣的代碼重複。 – hugomg 2011-05-04 21:03:50

回答

2

如果你真的想模擬多態性,你可以,它只是變得醜陋。

typedef struct Card_t Card; 
typedef struct 
{ 
    void (*print)(Card*); 
    int (*do_action)(Card*, struct GameState*, int); 
    /* other possibly card-specific functions here */ 
} CardMethods; 

struct Card_t 
{ 
    int value; 
    int cost; 
    CardMethods* vtab; 
}; 

int stdAct(Card* this, GameState* st, int choice) 
{ 
    this->vtab->print(this); //do this card's specific print function. 
    /* do common actions based on state&choice */ 
} 

int specialPrint1(Card* this) 
{ 
    stdPrint(this); //call parent print function 
    printf("something special here"); //add behavior 
} 

CardMethods standardCard={stdPrint, stdAct}; 
CardMethods specialCard1={specialPrint1, stdAct}; 
CardMethods specialCard2={stdPrint, specialAct1}; 
CardMethods specialCard3={specialPrint2, specialAct2}; 
static struct cardDefinitions[] = { 
{0, 1, &standardCard},  
{1, 3, &standardCard}, 
{2, 3, &specialCard1}, 
{2, 4, &specialCard2}, 
/*...*/ 
}; 


cardDefinitions[i].vtab->do_action(&cardDefinitions[i], state, choice) 

此時你正在做的大部分的C++編譯器的場景,你可能也只是使用C++的背後是什麼。

+0

啊是的,我想我可以做一個功能列表,並做前/後行爲..這將模擬裝飾 – 2011-05-05 01:07:26

2

有什麼回採你只需要創建像print_game_state(GAME_STATE *)子程序和在do_card功能使用它們?

int do_card0(...){ 
    print_game_state(...); 
    //other stuff 
} 

int do_card0(...){ 
    print_game_state(...); 
    //do different stuff 
} 

如果這不能解決你的問題,然後爲每個一塊卡行爲的類之間變化,並使用這些從外部函數創建函數。

struct Card{ 
    int value; 
    int cost; 
    int (*f1)(struct card* self); 
    int (*f2)(struct card* self); 
}; 

void my_function(Card* card){ 
    card->f1(card); 
    printf("something\n"); 
    card->f2(card); 
} 
+0

那麼,如果它是一個簡單的'printf',這將無濟於事。我想eat_a_lemon正在尋找類似Python的裝飾器......我想。 – 2011-05-04 20:59:51

+0

不,但它不理想,因爲它會產生重複 – 2011-05-04 21:00:02

+0

你不能在C中乾淨地做python風格的裝飾器。它沒有閉包。 (你可以從Python的明確的'self'變量中獲取靈感,並且盡一切努力通過) – hugomg 2011-05-04 21:02:47

0

如果我正確認識這個問題,你能不能簡單地創建一個共同的打印功能,需要一個特定的屬性集,並調用常用的打印功能從每個do_cardX功能?

C中沒有模板,所以你不能創建一個通用的單一的函數來在函數調用的時候實例化它的參數類型,即使你可以,你仍然必須創建一些類型每種功能都需要調用的專用打印功能,以打印您希望從每種特定類型的do_card()功能獲得的特定遊戲狀態信息。

+0

遊戲狀態打印在所有類型中都是相同的代碼。這個想法是不要在每個do_card函數中複製這段代碼。 – 2011-05-04 21:05:53

3

而不是在每個卡上調用do_action,通過與其他PARAMS您定義另一個函數沿卡片,有一個叫做動作的方法,然後再調用打印狀態的方法或任何

例如

//add a method like this 
int process_card(CARD inCard, GAME_STATE *state, int choice1, int choice2) 
{ 
    inCard.do_action(state, choice1, choice2); 
    print_state(state); 
} 

//last line changes to 
process_card(cardDefinitions[card_number], state, choice1, choice2); 

肯定是錯誤我的C是生鏽的,但這是我認爲的jist。