C-функция украшения / полиморфизм - PullRequest
2 голосов
/ 05 мая 2011

Можно ли как-нибудь выполнить код в базовой функции для всех типов действий? Я хочу выполнить поведение, общее для всех действий do_card. Другими словами, я хочу напечатать состояние игры, но я хочу избежать дублирования printf в каждой отдельной функции do_card, и вместо этого написать его один раз. Есть ли способ реализовать это в 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);

Ответы [ 4 ]

3 голосов
/ 05 мая 2011

вместо вызова do_action для каждой карты, передайте карту вместе с другими параметрами в другую функцию, которую вы определили, вызовите метод do action, затем вызовите метод состояния печати или любой другой

например

//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 ржавый, но я думаю, что это и есть черт.

2 голосов
/ 05 мая 2011

Если вы действительно хотите эмулировать полиморфизм, вы можете, это просто уродливо.

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 ++.

2 голосов
/ 05 мая 2011

Что-то мешает вам просто создавать подпрограммы, такие как 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 голосов
/ 05 мая 2011

Если я правильно понимаю этот вопрос, не можете ли вы просто создать общую функцию печати, которая принимает определенный набор атрибутов, и вызвать эту общую функцию печати из каждой из функций do_cardX?

В C нет шаблонов, поэтому вы не можете создать универсальную единственную функцию do_card(), которая бы создавала экземпляры ее типов аргументов в точке вызова функции, и даже если бы вы могли, вам все равно пришлось бы создать какой-то специализированный типФункция печати, которую должна вызывать каждая функция, чтобы напечатать информацию о конкретном игровом состоянии, которую вы хотите получить от каждого конкретного типа do_card() функции.

...