2

I have classes Deck, abstract class Card and Spell and Minion which are both derived from Class. I have vector<unique_ptr<Card> > of all existing Cards and now I want to place them into Decks. I want to use void Deck::addCard(<unique_ptr<Card>) overloads for Minion and Spell.

I've tried changing the arguments and parameters to "dumb" * pointer, or just Card (which can't work, I know), references, non-references etc...

Calling addCard

Deck tmp;
for( const auto & it : mAllCards )
{
  cout << typeid( *it ).name() << endl;
  tmp.addCard( it );
}

addCard functions

void Deck::addCard( const unique_ptr<Card> & card )
{
    cout << "basic" << endl;
}

void Deck::addCard( const unique_ptr<Minion> & minion )
{
    cout << "minion" << endl;
}

void Deck::addCard( const unique_ptr<Spell> & spell  )
{
    cout << "spell" << endl;
}

The problem is that the Card version is called everytime, not the variants for derived types. Althrough typeid says Minion or Spell, not Card.

5
  • Do you really use Deck tmp(); in the code? It is a function prototype for a function named tmp, which takes no parameters and returns a Deck. Commented May 7, 2019 at 7:49
  • Please post a minimal reproducible example you have omitted most of the relevant code. Commented May 7, 2019 at 7:49
  • What do you want to store in Deck? References to cards in a vector? Their copies? In the first case, just store references to Card. In the second case, you likely want some form of a clone pattern, see, e.g., stackoverflow.com/q/39905802/580083. Commented May 7, 2019 at 7:51
  • No, I don't, sorry, error in simplifying the code. Commented May 7, 2019 at 7:51
  • Yes, I want to make a copy, I'll look at it, thanks Commented May 7, 2019 at 7:54

1 Answer 1

3

It doesn't work because overloads in C++ are resolved at compile time.

You should considere using a virtual print function from Card.

Something like this.

class Card {
public:
    virtual void print() { std::cout << "basic" << std::endl; }
}

class Minion : public Card {
public:
    void print() override { std::cout << "minion" << std::endl; }
}

class Spell : public Card {
public:
    void print() override { std::cout << "spell" << std::endl; }
}

Then to use this print function you'll do this way.

void Deck::addCard(const unique_ptr<Card>& card)
{
    card.print();
}

Otherwise there's always double dispatch pattern or maybe visitor pattern.

Found all this in this old post.

Sign up to request clarification or add additional context in comments.

3 Comments

This doesn't really answer the question. addCard method should be a part of Deck class, not Card class, so making functions virtual is not helpful.
Yes, it works now, thank you. I wanted to have just Deck::AddCard not Card::AddToDeck, but it's not posibble from what I read. I will probably remove the AddCard and leave just AddToDeck, since the function makes no sense now, it only calls the other one.
Actually, I'm just making the print function virtual. The addCard is still a part of Deck.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.