Search code examples
c++copy-constructor

How to define constructor c++


I have only been working with C++ for a year now and I am hoping to gain a better understanding of abstraction with my current project. I created a Black Jack card game from my book 'Beginning C++ Through Game Programming'. The game works, but I am working on a menu option that restarts the game, adds scores and allows you to view the scores via fstream.

This is what the menu section looks like inheriting from the base class Game:

class Menu
{
public:
    Menu();
    ~Menu();

private:
    Game m_game;
    //saves scores to fstream from class Player m_player;

    //menu options 
    void choice();

};

Menu::Menu() {} //no appropriate default constructor available for Game

Menu::~Menu() {}

void Menu::choice()
{
    char respond;
    bool run = true;
    cout << "Would you like to [R]estart the game, [A]dd new score, [V]iew the score sheet or [Q]uit?" << endl;
    cin >> respond;
    switch (respond)
    {
    case 'R': m_game.play(); break;
    case 'A': //add new score to fstream
    case 'V': //view score txt file
    case 'Q': run = false; break;
    }
}

I am pretty confused about how to create the default constructor for this section, even with the examples from the book.

The constructor for the Game class looks like:

class Game
{
public:
    Game(const vector<string>& names);
    ~Game();

    //plays game
    void play();

private:
    Deck m_deck;
    House m_house;
    vector<Player> m_players;

};

I'm hoping to get an explanation or example. Thank you for your help!


Solution

  • Your Menu class (before calling the constructor) wants to create a Game instance using default constructor (without parameters) but Game class don't have a default constructor (because if you create any constructor, default constructor is not created automatically).

    You have three options:

    1. Provide an empty constructor in your Game class next to your current constructor that gets a vector of strings.
    2. Make Game m_game; be Game m_game = Game(vector<string>());. This will be executed before the constructor and this enables you to set default values of any class member. Downside of this solution is that copy constructor will be called (first, temporary object will be made and then it will be copied to your instance, it could be optimized by the compiler but not always; if you don't know what it is, check this: https://www.geeksforgeeks.org/copy-constructor-in-cpp/)
    3. Use something that is called initializer list in c++. There are some questions in this topic on stack overflow, for example here (C++ - No appropriate default constructor available). In this solution you don't make any temporal objects (like in the first solution). Your constructor would look like this: Menu::Menu() : m_game(vector<string>()) {}.

    The first and third options are the best. You have to decide which one to use.

    You can replace vector<string>() with not empty vector of course.

    You should also look here: https://www.learncpp.com/cpp-tutorial/constructor-member-initializer-lists/. There is explained everything about the initializer list.

    The other issue here is that you shouldn't create your Game instance inside the Menu class (this is an architectural mistake). You can for example pass a pointer or reference to choice() method or Menu class constructor and store just Game instance address (go with the latter if Game instance will be used by several methods). More appropriate approach would be that game contains a Menu instance.