2011-05-04 71 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。