使用虚拟纯函数访问字段的分段错误

Segmentation fault with access to field using virtual pure function

本文关键字:字段 分段 错误 访问 函数 虚拟      更新时间:2023-10-16

我读了很多关于纯虚拟调用的错误,但我没有弄清楚我的代码出了什么问题:

我编写了国际象棋游戏,使用多态性。

这里有一些代码:

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;
};

和鲁克.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');
}

板::p板

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 = board[i][j]->getUnicodeSymbol();

我得到:

称为纯虚拟方法

我没有在构造函数或析构函数中调用函数

virtual 关键字放入上述~Piece()析构函数后,此问题就解决了。但现在在同一条线上我得到了

信号:SIGSEGV(分段故障)

有什么想法吗?

这里有一些更多信息:

我在国际象棋主.cpp内宣布棋盘:

棋盘游戏;

然后我像这样发送到void playGame(Board boardGame):

玩游戏(棋盘游戏);

在里面我发送到void getNextMove(Board board,string whitePlayer,string blackPlayer),就像这样:

getNextMove(boardGame, whitePlayer, blackPlayer);

然后我正在使用:

boardGame.print();

我假设你有一个类型Board的对象,你复制了它,但你没有复制构造函数,我还假设Board::board是动态分配的。

这将导致复制、分配或销毁问题。(自读)

您需要遵守三法则,并为Board的复制构造函数、赋值运算符和析构函数提供有效的实现。

或者,您可以将Board::board声明为指针向量,而不必担心内存管理。

这都是基于一个假设,如果你已经这样做了,那么这个答案就不适用了。