Деструкторы и указатели на атрибуты класса - PullRequest
0 голосов
/ 18 декабря 2011

У меня есть этот класс ChessBoard, вот его заголовок:

class ChessBoard
{
    Field** board;
    Color currentColor; 

public:
    ChessBoard();
    ChessBoard(const ChessBoard&);
    Field* findField(std::string);
    ChessBoard& operator = (const ChessBoard&);

    bool checkIfFieldHasFigure(std::string);


    void writeOneState(SahApi*);
    void playAllMoves(std::istream*, SahApi*);
    void playMove(std::string);
    ~ChessBoard();

};

И у меня есть его конструктор, который создает начальный этап шахматной доски: (довольно отвратительно, я знаю :))

ChessBoard::ChessBoard()
{
    int i, j;
    Error err;
    board = new Field*[8];
    if(!board)
    {
        err.writeToOutput(1);
        exit(1);
    }
    for(i = 0; i < 8; i++)
    {
        board[i] = new Field[8];
        if(!board[i])
        {
            err.writeToOutput(1);
            exit(1);
        }
    }
    currentColor = WHITE;
    char c;
    std::string s;
    Figure f;
    for(i = 0; i < 8; i++)
        for(j = 0; j < 8; j++)
        {
            s.clear();
            c = i + 'A';
            s.push_back(c);
            c = j + '1';
            s.push_back(c);
            board[i][j].position.assign(s);

            if((j > 1) && (j < 6))
                board[i][j].hasFigure = 0;
            else board[i][j].hasFigure = 1;

            if((i+j+2) % 2)
                board[i][j].color = WHITE;
            else board[i][j].color = BLACK;

            if( ((j==0)||(j==7)) && ((i==0)||(i==7)) )
            {
                Rook* r = new Rook(((j==0)?WHITE:BLACK), s);
                if(!r)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(r);
            }
            else if( ((i==1)||(i==6)) && ((j==0)||(j==7)) )
            {
                Knight* n = new Knight(((j==0)?WHITE:BLACK), s);
                if(!n)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(n);
            }
            else if( ((i==2)||(i==5)) && ((j==0)||(j==7)) )
            {
                Bishop* b = new Bishop(((j==0)?WHITE:BLACK), s);
                if(!b)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(b);
            }
            else if( (i==3) && ((j==0)||(j==7)))
            {
                Queen* q = new Queen(((j==0)?WHITE:BLACK), s);
                if(!q)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(q);
            }
            else if( (i==4) && ((j==0)||(j==7)) )
            {
                King* k = new King(((j==0)?WHITE:BLACK), s);
                if(!k)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(k);
            }
            else if( (j==1) || (j==6) )
            {
                Pawn* p = new Pawn(((j==1)?WHITE:BLACK), s);
                if(!p)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(p);
            }
        }       
}

Мне также нужен деструктор для ChessBoard, который выглядит примерно так:

ChessBoard::~ChessBoard()
{
    //for(int i = 0; i < 8; i++)
    //  delete board[i];
    delete [] board;
}

Причина, по которой это закомментировано, - мой первый вопрос:

1.Почему я не могу удалить все свои поля с помощью написанного выше метода? Когда я пытаюсь это сделать, программа выдает ошибку «Тип блока действителен», которая, как я знаю, вызвана попыткой удалить несуществующую память.Когда я это комментирую, программа работает отлично.А шахматная доска - это матрица 8х8, поэтому я могу удалить ее, как я пытался здесь.

Мой второй вопрос:

2.Как я могу удалить указатели на фигуры (King, Queen, Rook, ...), которые существуют в моем конструкторе для шахматной доски? Это сбивает с толку, потому что эти указатели используются как части моей шахматной доски, и я использую их доконец программы.Когда программа заканчивается, мне нужно освободить память, но я не знаю, как получить доступ к этим указателям.Сами рисунки автоматически удаляются, потому что все они не являются указателями. Нужно ли вообще удалять эти указатели , видя, как я их использую до конца, а потом все освобождается?

1 Ответ

6 голосов
/ 18 декабря 2011
  1. Общее правило для нового / удаления состоит в том, что вызовы должны соответствовать друг другу.Вы создаете свою доску с помощью

    board = new Field*[8];
    for(i = 0; i < 8; i++)
    {
        board[i] = new Field[8];
    }
    

    Вам нужно будет удалить свою доску таким же образом, но в обратном направлении:

    for(i = 0; i < 8; i++)
    {
        delete [] board[i];
    }
    delete[] board;
    

    Так как это не работает, я предполагаю, что ваша проблемадвойное удаление.Что-то еще освобождает массив.Возможно ли, что у вас есть копия ChessBoard, которая указывает на то же поле **?

  2. Вам придется удалить свои фигуры аналогичным образом.

    for (int x = 0; x < 8; x ++)
    for (int y = 0; y < 8 ;y ++)
    if (board[y][x] != NULL)
         delete board[y][x];
    

    Этот код будет работать до тех пор, пока ваш код для удаления фигуры с доски удалит эту фигуру и установит положение этой фигуры в NULL.

    2b.Вторая часть вашего вопроса состояла в том, нужно ли вам вообще что-либо удалять, потому что программа заканчивается.Вы правы в том, что вам не нужно ничего удалять, если вы все равно собираетесь выйти немедленно, ОС все равно освободит всю эту память для вас.

Однако, как правило, следует делать это, обычно в большинстве случаев вы изменяете большинство программ, позволяя им запускаться несколько раз, и тогда у будет утечка памяти при каждом запуске.немного больше памяти.


Вот так и решите свой вопрос как задано.Тем не менее, я настоятельно рекомендую вам изменить стиль большей части этого кода и удалить все динамическое распределение.

Во-первых, используйте обычный статический массив (Field [8] [8]) для храненияполе.Я имею в виду, когда шахматное поле меняет размер?

Во-вторых, сохраняйте фигуры по значению. Класс вашего поля уже сохраняется, если фигура находится в локации.Также пусть класс Field хранит перечисление, также представляющее тип.Нет смысла использовать динамическое распределение для ваших фигур.

В-третьих, нет необходимости проверять, равен ли возврат new NULL.Если произойдет ошибка, она выдаст исключение, и ваша программа остановится (как и должно быть, вы мало что можете сделать, когда у вас недостаточно памяти).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...