Ошибка сегментации с доступом к полю с использованием виртуальной чистой функции

0

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

Я запрограммировал шахматную игру, используя полиморфизм.

здесь некоторый код:

Piece.hpp (Родитель для всех игровых предметов)

class Piece
{
private:
    char _player;
    virtual int isMoveLegalForSpecificPiece(int positionRow, int positionCol, int targetRow,
                                            int targetCol, Piece *board[8][8]) = 0;
public:
    ~Piece()
    {
    }
    Piece(char player);
    virtual int isMoveLegal(int positionRow, int positionCol, int targetRow, int targetCol,
                            Piece *board[8][8]);
    char getPlayer();
    virtual char getSign() const = 0;
    virtual std::string getUnicodeSymbol() const = 0;
};

Rook.hpp (например)

#include "Piece.hpp"

class Rook : public virtual Piece {
private:
    std::string _unicode = "265C";
    virtual int isMoveLegalForSpecificPiece(int positionRow, int positionCol, int targetRow,
                                            int targetCol, Piece *board[8][8]);
public:
    Rook(char player) : Piece(player){}
    ~Rook() {}
    virtual std::string getUnicodeSymbol() const;
    char getSign() const;
};

и Rook.cpp

#include "Rook.hpp"
char Rook::getSign() const {return 'r';}
int Rook::isMoveLegalForSpecificPiece(int positionRow, int positionCol, int targetRow,
                                      int targetCol, Piece *board[8][8]) {
    if (positionRow == targetRow) {
        int rightOrLeft = (targetCol - positionCol > 0) ? 1 : -1;
        for (int i = positionCol + rightOrLeft; i != targetCol; i += rightOrLeft) {
            if (board[positionRow][i] != 0) {return 0;  }
        }
        return 1;
    }
    else if (positionCol == targetCol)  {
        int upOrDown = (targetRow - positionRow > 0) ? 1 : -1;
        for (int i = positionRow + upOrDown; i != targetRow; i += upOrDown) {
            if (board[i][positionCol] != 0) {return 0;}
        }
        return 1;
    }
    return 0;
}
std::string Rook::getUnicodeSymbol() const {return _unicode;}

Совет :: Совет()

Board::Board()  {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            board[i][j] = 0;
        }
    }
    for (int i = 0; i < 8; i++) {
        board[1][i] = new Pawn('w');
        board[6][i] = new Pawn('b');
    }   
    board[7][0] = new Rook('b');
    board[0][0] = new Rook('w');
    board[7][1] = new Knight('b');
    board[0][1] = new Knight('w');
    board[7][2] = new Bishop('b');
    board[0][2] = new Bishop('w');
    board[7][3] = new King('b');
    board[0][3] = new King('w');
    board[7][4] = new Queen('b');
    board[0][4] = new Queen('w');
    board[7][5] = new Bishop('b');
    board[0][5] = new Bishop('w');
    board[7][6] = new Knight('b');
    board[0][6] = new Knight('w');
    board[7][7] = new Rook('b');
    board[0][7] = new Rook('w');
}

Совет :: печать

void Board::print() {
    printRowLetters();
    for (int i = 7; i >= 0; i--){
        cout << (char) ('1' + i) << " ";
        for (int j = 7; j >= 0; j--) {
            string isColor = "0";
            string pieceUnicode = " ";
            if (board[i][j])    {
                isColor = (board[i][j]->getPlayer() == 'w') ? "37" : "30";
                pieceUnicode = board[i][j]->getUnicodeSymbol();
            }
        //some more code..
        }
    }
}

я застрял в этой строке:

pieceUnicode = доска [i] [j] → getUnicodeSymbol();

я получил:

чистый виртуальный метод, называемый

я не вызывал функцию внутри конструктора или деструктора

После размещения ключевого слова virtual в описанном выше ~Piece() деструкторе эта проблема была решена. Но теперь на той же линии я получаю

Сигнал: SIGSEGV (ошибка сегментации)

есть идеи?

здесь дополнительная информация:

я объявляю совет внутри main chess.cpp:

Board boardGame;

то я посылаю void playGame (Board boardGame) следующим образом:

пустяки (BoardGame);

и внутри я посылаю void getNextMove (Board board, string whitePlayer, string blackPlayer) следующим образом:

getNextMove (boardGame, whitePlayer, blackPlayer);

и затем я использую:

boardGame.print();

  • 0
    TL; DR; Сделайте деструкторы абстрактных классов virtual : virtual ~Piece() {} .
  • 0
    @ πάνταῥεῖ Спасибо! теперь я получаю сигнал: SIGSEGV (ошибка сегментации). любая идея?
Показать ещё 11 комментариев
Теги:
polymorphism
pure-virtual
pure-function

1 ответ

2

Я предполагаю, что у вас есть объект типа Board и вы делаете его копии, но у вас нет конструктора копирования, и я также предполагаю, что Board::board динамически распределена.

Это вызовет проблемы с копированием, назначением или уничтожением. (Прочти меня)

Вы должны подчиняться правилу из трех и предоставлять правильные реализации для конструктора копирования, оператора присваивания и деструктора Board.

Или вы могли бы объявить Board::board как вектор указателей и не беспокоиться об управлении памятью.

Все это основано на предположении, если вы уже это сделаете, тогда этот ответ не применяется.

  • 0
    Спасибо! просто чтобы убедиться, что я понял: мне нужно создать конструктор копирования в Board, потому что когда я посылаю его из функции в функцию, данные, которые он удерживает, теряются
  • 0
    @AviadLevy хорошо ... не совсем - прочитайте подробный ответ по ссылке. Когда вы передаете по значению, вы делаете поверхностную копию, а когда функция завершается, копия удаляется, что удаляет элементы, если у нее есть деструктор.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню