Итак, у меня проблема с этим назначением класса, мы настроены на код игры в стиле «крестики-нолики». Я подумал, что было бы неплохо иметь 2 версии, такие как оригинал, с 3 по ширине, а затем с 4 по горизонтали. Итак, вот базовый класс с проблемными функциями

Вот минимум, который не оставляет ничего вырезанного

Main.cpp

#include "tic_tac_toe.h"
#include "tic_tac_toe_3.h"
#include "tic_tac_toe_4.h"
int main()
{
  std::vector <std::reference_wrapper<Tic_tac_toe>> games;

  string playerOption{ "" };

  bool isRunning{ true }, error{ true };
  int position{ 0 }, playerInt{ 0 };
  char option{ ' ' };



  //main loop
  while (isRunning)
  {

     cout << "Tic Tac Toe game 3 or 4: ";
     cin >> playerInt;

     if (playerInt == 3)
     {
         cout << "Executing tic tac toe 3";
         Tic_tac_toe_3 game3;
         games.push_back(game3);
     }
     else if (playerInt == 4)
     {
         cout << "Executing tic tac toe 4";
         tic_tac_toe_4 game4;
         games.push_back(game4);
     }

     //allows for constant looping to get user to input X or O. So program wont blow up
     while (error)
     {
         cout << "Player 1, X or O: ";
         cin >> playerOption;
         try
         {
             games[games.size() - 1].get().start_game(playerOption); //the .get gets the stored reference
             error = false;
             cout << "\n"; //to add a break in the text
         }
         catch (Error e)
         {
             cout << e.get_message();
         }
     }

     try
     {
         cin >> games[games.size() - 1].get(); //FAIL POINT IMO
         cout << games[games.size() - 1].get();
     }

     catch(Error e)
     {
         cout << e.get_message();
     }
 }
return 0;
}

Tic_tac_toe.h

#include vector

using std::string;

class Tic_tac_toe
{
  public:
    Tic_tac_toe(int size) : pegs(size* size, " ") { } //multiply 3 or 4 by itself for 9 or 16

    void start_game(std::string first_player);
    void mark_board(int position);

    friend std::ostream& operator<<(std::ostream& out, const Tic_tac_toe& t);
    friend std::istream& operator>>(std::istream& in, Tic_tac_toe& b);

    string get_player() const { return player; }
    string get_winner() const { return winner; }

protected:

    std::vector<string> pegs; //initializes a vector of x elements with each being a space.

private: //most logic goes within the private functions

    void set_next_player();

    string player;
}

Tic_tac_toe.cpp

{
void Tic_tac_toe::start_game(std::string first_player)
{
    if (first_player == "X" || first_player == "O")
    {
        player = first_player;
        clearBoard();
    }
    else { throw Error("Player must be X or O\n"); }
}

void Tic_tac_toe::mark_board(int position)
{
    if (position < 1 || position > 9)
    {
        throw Error("Position must be 1 to 9.\n");
    }
    else if (player == "")
    {
        throw Error("Must start game first.\n");
    } 
    else
    {
        pegs[(position - 1)] = player; //minus one for the index
        set_next_player();
    }
}

std::ostream& operator<<(std::ostream& out, const Tic_tac_toe& b) 
{
    std::cout << "\n"; //formatting purposes
    for (std::size_t i = 0; i < 9; i += 3) // += 3 for new row
    {
        out << b.pegs[i] + " | " + b.pegs[i + 1] + " | " + b.pegs[i + 2] + "\n";
    }
    return out;
}

std::istream& operator>>(std::istream& in, Tic_tac_toe& b)
{
    std::cout << "Pegs size" << b.pegs.size();
    int pos{ 0 };
    std::cout << "Player " << b.get_player() << " enter a position: ";
    in >> pos;
    b.mark_board(pos);

    return in;
}
}

Tic_tac_toe_4 // 4 и 3 точно такие же банкоматы

class Tic_tac_toe_4 : public Tic_tac_toe
{

public:

tic_tac_toe_4() : Tic_tac_toe(4) { std::cout << "Passing to constructor"; }

}
c++
0
DiamondMastiff 15 Апр 2020 в 19:21

1 ответ

Лучший ответ

Ваша программа имеет неопределенное поведение, потому что вы нажимаете ссылки на локальные переменные, такие как

Tic_tac_toe_3 game3;

В games. Когда эти переменные покидают свою область видимости, ссылки в games становятся недействительными, и попытка использовать их позже будет иметь неопределенное поведение.

Если вам нужен контейнер, который владеет объектами Tic_tac_toe, используйте

std::vector<std::unique_ptr<Tic_tac_toe>>

Вместо этого в качестве типа и создайте объекты с помощью std::make_unique. Тогда объекты будут жить до тех пор, пока принадлежащие им векторные элементы не будут уничтожены.

1
walnut 15 Апр 2020 в 17:27