C++ 程序在使用 -> 运算符后崩溃



我正在做一个用C++设计游戏的项目,当我试图从玩家那里获得移动时,我的程序不断崩溃。该程序允许用户为两个玩家中的每一个选择是电脑玩家还是人类玩家。如果是人类玩家,它会收集玩家的名字。

当程序启动时,我的主类创建一个游戏对象,运行selectPlayers()函数,然后运行play()数。程序正在加载,向我询问每个玩家的人或电脑,收集人的名字并显示棋盘(在play()函数中显示),然后它崩溃,弹出一个窗口,显示消息

程序停止工作,windows正在寻找解决方案

在下面的代码中添加了一条注释来显示问题所在。如果我在那行上面放了一个cout,它就会打印出来,但在那行之后什么都没有打印出来。。。如果我在HumanPlayer类的makeMove方法的第一行上放了一个cout,它不会被打印出来,所以程序在进入该方法之前就崩溃了。

这是我的游戏类的标题:

#include "Board.h"
#include "Player.h"
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
class Game
{
    Board b;
    int turn;
    bool winner;
    Player* player1;
    Player* player2;
public:
    Game();
    ~Game();
    void selectPlayers();
    Player* nextPlayer() const;
    void play();
    void announceWinner();
};
#endif // GAME_H_INCLUDED

以及类本身:

#include "Game.h"
#include "HumanPlayer.h"
#include "RandomPlayer.h"
#include <iostream>
Game::Game()
{
    b.reset();
    turn = 1;
    winner = false;
}
Game::~Game()
{
}
void Game::selectPlayers()
{
    int x = 0;
    std::string type;
    std::string name;
    std::cout << "Enter type for Player 1 (Human/Computer): ";
    std::cin >> type;
    while(x == 0)
    {
        if(type.compare("Human") == 0)
        {
            x = 1;
            std::cout << "Enter name for Player 1: ";
            std::cin >> name;
            HumanPlayer p(name, LIGHT);
            HumanPlayer * player1 = &p;
        }
        else if(type.compare("Computer") == 0)
        {
            x = 1;
            RandomPlayer p(1, LIGHT);
            RandomPlayer * player1 = &p;
        }
        else
        {
            std::cout << "Please enter Human or Computer for Player 1: ";
            std::cin >> type;
        }
    }
    std::cout << "Enter type for Player 2 (Human/Computer): ";
    std::cin >> type;
    x = 0;
    while(x == 0)
    {
        if(type.compare("Human") == 0)
        {
            x = 1;
            std::cout << "Enter name for Player 2: ";
            std::cin >> name;
            HumanPlayer p(name, DARK);
            HumanPlayer * player2 = &p;
        }
        else if(type.compare("Computer") == 0)
        {
            x = 1;
            RandomPlayer p(2, DARK);
            RandomPlayer * player2 = &p;
        }
        else
        {
            std::cout << "Please enter Human or Computer for Player 2: ";
            std::cin >> type;
        }
    }
}
Player* Game::nextPlayer() const
{
}
void Game::play()
{
    while(winner == false)
    {
        b.display();
        if(turn%2 == 1)
        {
            player1->makeMove(b); //PROGRAM CRASHES HERE
            ++turn;
        }
        else
        {
            player2->makeMove(b);
            ++turn;
        }
    }
}
void Game::announceWinner()
{
}

任何帮助都会很棒,谢谢大家。

您需要像这样更改所有代码:

        HumanPlayer p(name, LIGHT);
        HumanPlayer * player1 = &p;

到此:

        player1 = new HumanPlayer (name, LIGHT);

在代码中,您创建了一个局部变量,并为其赋值。类中的成员变量从未初始化。

之所以发生崩溃,是因为player1是一个野生指针(即它不包含合法值)。看起来您正在尝试为其分配值,但操作不正确,如下所示:

HumanPlayer p(name, LIGHT);
HumanPlayer * player1 = &p;

这里有两个问题。首先,您要声明的对象是一个局部变量,所以试图存储指向它的指针是一个很大的错误。它超出了范围,在几行之内就被摧毁了。其次,您在这里声明了一个完全独立的player指针,而不是使用该类成员的指针。结果是,您将一个局部变量存储在一个局部指针中,因此您的程序以后无需处理任何内容。

相反,这些行应该实例化堆(或空闲存储)上播放器类的新实例。传统的C++会使用这样的"新"操作符:

player1 = new HumanPlayer(name, LIGHT);

然而,如果您使用的是现代编译器,那么实际上应该使用智能指针。这意味着您的Game类应该声明如下的指针:

std::shared_ptr<Player> player1;

分配给他们的代码应该这样做:

player1 = make_shared<HumanPlayer>(name, LIGHT);

显然,您也需要对player2进行类似的更改。

您永远不会在Game.selectPlayers()中初始化player1player2。相反,您创建一个HumanRandomPlayer类型的新临时变量,该变量在方法结束后超出范围。

您的类中有未初始化的数据,因为您没有初始化指针。将它们设置为NULL,或者使用指针交换器(shared_ptrunique_ptr)来管理它们,因为它们将为您负责初始化。

与C#或Java等语言不同,C++不会将成员变量设置为默认值,除非它们有默认构造函数,而指针没有!

最新更新