1

i am dealing with a c++ school project. i want to store child card object inside parent card object in main function because i need to set card inside the library (std::vector<card> _library;) as same type.

what i need to use in main function to store child classes inside parent classes?

definition of classes and main function :

#ifndef CARD_H
#define CARD_H

class player;
class card
{
protected:
    std::string _name;
    std::string _type;
    player _owner;
public:
    card();
    card(std::string name, std::string type);
    void setOwner(player&);
    
    virtual void play();

};
#endif
#ifndef  ENCHANTMENT_H
#define ENCHANTMENT_H 

class enchantment :public card
{

public:
    enchantment()
    enchantment(std::string name, std::string type);

    void play() override;
};
#ifndef CREATURE_H 
#define CREATURE_H 


class creature :public card
{
public:
    creature();
    creature(std::string name, std::string type);

    void play()override;
    
};
#endif
#ifndef PLAYER_H
#define PLAYER_H 

class card;
class player
{
protected:
    std::string _name;

    std::vector<card> _hand;
    std::vector<card> _library;
    std::vector<card> _in_play;
    std::vector<card> _discards;

public:
    player();
    player(std::string name);
    

    //setter functions
    void setLibrary(std::vector<card>);

};

#endif // !PLAYER_H
int main() {


    player p1("player1");

    creature p1Soldier01("Soldier", "Creature");
    creature p1Soldier02("Soldier", "Creature");

    enchantment p1Rage01("Rage", "Enchantment");
    enchantment p1Rage01("Rage", "Enchantment");

    std::vector<card> player1Cards(4);
    //this is the part i need help.


    p1.setLibrary(player1Cards);
}
wdafoe666
  • 109
  • 9
  • 1
    You've forgotten to ask a question. What doesn't work? Compilation errors? What misbehavior you see? – Alexey S. Larionov May 17 '21 at 11:43
  • 1
    `player _owner;` It cannot work this way, you can either have a (smart) pointer to `player` or not store the owner in the card at all. – n. m. could be an AI May 17 '21 at 11:44
  • In addition, `std::vector` also cannot work, you need a vector of (smart) pointers here too. See e.g. [here](https://stackoverflow.com/questions/15188894/why-doesnt-polymorphism-work-without-pointers-references) or [here](https://stackoverflow.com/questions/8777724/store-derived-class-objects-in-base-class-variables/). – n. m. could be an AI May 17 '21 at 11:48
  • did you meant vector that inside main function? or player class? – wdafoe666 May 17 '21 at 11:51
  • Preferably don't use underscores before identifiers in C++ (I know it's common in other languages) unless you know what you are doing. Often these are reserved (check [cppref](https://en.cppreference.com/w/cpp/language/identifiers)). Instead use `m_name` or just `name`. – JHBonarius May 17 '21 at 12:38

2 Answers2

0

Nobody answered yet, but a common approach to this is either dynamic polymorphism. Possible implementation:

std::vector<std::unique_ptr<card>> allCards; 
allCards.push_back(std::make_unique<enchantment>("foo", "bar"));
std::vector<card*> in_hand; // only has references to the existing card objects.
in_hand.push_back(allCards[0].get());

(p.s. DONT forget the virtual destructor in the base class!)

Or static polymorphism, where a common base class isn't even needed

using Card = std::variant<Enchantment, Creature, ...>;
std::vector<Card> cards;

You don't need to store the child class in the parent class (with some exceptions like CRTP). Usually you can use polymorphim, i.e. override virtual functions, like in the case of play(). (For static polymorphism/variant you will need a visitor).

p.s. card cannot have a player object, as player is not a complete type. But your don't want a card to "own" a player object at all. Instead you should point to an existing player object, i.e. player*.

example

JHBonarius
  • 10,824
  • 3
  • 22
  • 41
0

what i need to use in main function to store child classes inside parent classes?

That is not possible directly. You see, child classes contain an instance of their parent inside them. So, if the child contains an instance of the parent which contains an instance of the child which contains an instance of the parent which contains an instance of the child which contains ... can you see the problem here?

Another way to explain the problem is that "containing" something (as a member) necessitates the definition of that something before defining the container. So, the parent needs the child defined before itself, and the child requires the parent be defined before itself. There's no way to order the definitions to satisfy both requirements.

Something like this is possible with indirection: A parent class can indirectly refer or point to an instance of a child class. Pointing doesn't necessitate the definition of the pointed type.

eerorika
  • 232,697
  • 12
  • 197
  • 326