After a few days of my question being closed, and my edits that would answer all of the questions in the comments not being approved, I have decided to re-post with a few changes.
I am new to c , but I am an experienced programmer. I am trying to create a chess engine, as I have done it in python but I want it faster. I am storing my chess board as a 2d array of Piece pointers.
chessBoard.h
#include <iostream>
#include "pieces.h"
class Chess
{
private:
Piece* board[8][8] = {};
public:
Chess();
void print_board();
};
pieces.h
enum PieceType {
pawn, knight, bishop, rook, queen, king
};
enum Colour {
white, black
};
class Piece {
protected:
PieceType pieceType;
Colour colour;
public:
char symbol;
Piece(Colour colour);
};
class Pawn : public Piece {
public:
Pawn(Colour colour);
};
// The rest of the pieces are defined in the same way
pieces.cpp
#include "pieces.h"
Piece::Piece(Colour colour) {
this->colour = colour;
}
Pawn::Pawn(Colour colour) : Piece(colour) {
this->pieceType = pawn;
this->symbol = (colour == white) ? 'P' : 'p';
}
// The rest of the pieces constructors are the same
chessBoard.cpp
Chess::Chess()
{
// The back row of black pieces
Rook bq_r(black);
Knight bq_n(black);
Bishop bq_b(black);
Queen bq_q(black);
King bk_k(black);
Bishop bk_b(black);
Knight bk_n(black);
Rook bk_r(black);
board[0][0] = &bq_r;
board[0][1] = &bq_n;
board[0][2] = &bq_b;
board[0][3] = &bq_q;
board[0][4] = &bk_k;
board[0][5] = &bk_b;
board[0][6] = &bk_n;
board[0][7] = &bk_r;
}
void Chess::print_board() {
for (int i = 0; i < 8; i ) {
for (int j = 0; j < 8; j ) {
if (board[i][j]) {
std::cout << board[i][j]->symbol;
std::cout << " ";
} else {
std::cout << ". ";
}
}
std::cout << std::endl;
}
}
main.cpp
#include "chessBoard.h"
int main()
{
Chess chess;
chess.print_board();
return 1;
}
I understand this is a lot of code, and I wish I could post only the relevant information, but unfortunately I have no clue what the problem was, and most of the comments on my last post asked for more info. If needed the complete code, it can be found here:
This is a screenshot from after the first iteration, after encountering the std::cout on line 4 of the printBoard() function.
I have been stuck on this problem for 2 days, researching and debugging, and I've found nothing. I'm sure it's something simple I'm doing wrong, I just can't find it. Please comment if you need any more info.
Thank you
CodePudding user response:
The accepted answer fixes the object lifetime problem by using dynamic allocation to create heap objects, but it should be noted that polymorphism on a base class pointer doesn't require dynamic allocation (I'm assuming you intend to add virtual
functions later).
The various derived pieces could simply be data members of the Chess
object, which often offers better performance and fewer pitfalls than dynamic allocation (moving the pointers around the board correctly may also be needlessly cumbersome with unique_ptr
):
class Chess {
private:
Piece* board[8][8] = {};
Rook m_white_rook;
Knight m_white_knight;
// ...all pieces here...
public:
Chess() :
m_white_rook(Colour::white),
m_white_knight(Colour::white),
// ...initialize pieces here...
{
board[0][0] = &m_white_rook;
board[0][1] = &m_white_knight;
// ...assign simple, non-owning pointers to the board...
}
};
CodePudding user response:
The objects bq_r
etc. defined in your Chess::Chess()
constructor have their lifetimes end when the constructor finishes, so the array is full of dangling pointers which can't validly be used.
I'd recommend instead:
#include <memory>
class Chess
{
private:
std::unique_ptr<Piece> board[8][8] = {};
public:
Chess();
void print_board();
};
Chess::Chess()
{
board[0][0] = std::make_unique<Rook>(black);
board[0][1] = std::make_unique<Knight>(black);
board[0][2] = std::make_unique<Bishop>(black);
board[0][3] = std::make_unique<Queen>(black);
board[0][4] = std::make_unique<King>(black);
board[0][5] = std::make_unique<Bishop>(black);
board[0][6] = std::make_unique<Knight>(black);
board[0][7] = std::make_unique<Rook>(black);
for (auto& pawn_pos : board[1])
pawn_pos = std::make_unique<Pawn>(black);
// ...
}
Since the unique_ptr
s will clean up by deleting a pointer to base class Piece
which actually points at other class types, that class needs a virtual destructor:
class Piece {
public:
// ...
virtual ~Piece() = default;
};