1

Consider a card game (something like Magic or Legends of Runeterra) program, with BaseCard, Deck and GameState classes/structs. The way I've conceptualized the relationship between these classes would be something like this:

BaseCard.hpp

struct GameState;

class BaseCard
{
public:
    virtual void DoEffect(GameState &gameState) = 0;
};

Deck.hpp

struct Deck
{
public:
    std::vector<std::unique_ptr<BaseCard>> drawPile;
    std::vector<std::unique_ptr<BaseCard>> discardPile;
    std::vector<std::unique_ptr<BaseCard>> hand;
};

GameState.hpp

struct GameState
{
    std::unique_ptr<Deck> deck;
};

The idea is that cards might have a variety of different effects that can change the GameState, like draw cards, alter properties of cards currently in hand, recover player health and so on, which would be implemented in DoEffect. I want the possibilities of what a card can do to be very flexible and I can't think of a way to that which doesn't involve passing the GameState to the card, but at the same time the cards are also inherently part of the game state.

Naturally I can get the code to compile by using a forward declaration in BaseCard.hpp then including GameState.hpp in the cpp files with the concrete implementations of the classes that inherit BaseCard, but this feels kinda "hacky" to me...

So my question here is whether this type of pattern is actually ok/normal in C++, and if not, what are possible alternatives.

3
  • 1
    "whether this type of pattern is actually ok/normal in C++" Yes.
    – Caleth
    Oct 31, 2022 at 10:13
  • As an aside: you probably don't need std::unique_ptr<Deck> unless you plan subclasses of Deck
    – Caleth
    Oct 31, 2022 at 10:14
  • This kind of forward declaration has practically no contents. All you can do is declare that a name is a struct or a class. You can’t even forward declare that a class is a subclass of a known class. I think that kind of use is perfectly fine.
    – gnasher729
    Nov 1, 2022 at 21:11

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.