user2997491
user2997491

Reputation: 135

C++ Array of interface base classes for chess

I am chasing error messages around in circles trying to figure out how I can get what I need working.

I am making a chess game where each chessmen is a class and there is an interface class named Piece.

Piece.h

class Piece {
public:
    virtual ~Piece() {};
    /*
     * Verifies the move on a per-piece basis. If the move is valid, make the changes on the board and return true, false otherwise.
     *
     * @param b             Reference to the board
     * @param toLocation    Where to move the piece
     * @return bool         If the move is valid
     */
    virtual bool move(Board &b, std::pair<int, int> toLocation) { return false; }

protected:
    Piece(GameData::Color _c) { c = _c; }
    GameData::Color c;
};

Pawn.h

class Pawn : Piece {
public:
    Pawn(GameData::Color _c);
    virtual ~Pawn();
    bool move(Board &b, std::pair<int, int> toLocation);
};

I cannot get this setup working though.

I get an error:

Pawn::Pawn(GameData::Color _c) : c(_c) {
no matching function for call to Piece::Piece()

I change the visibility of Piece to:

class Pawn : public Piece

But I get loads more errors where I don't have an empty constructor for piece again.

I am setting this up to try and make a 2D array of Pieces to represent the board:

board = new Piece**[SIZE];
for(int i = 0; i < SIZE; ++i)
    board[i] = new Piece*[SIZE];
/* Setup initial positions */
board[0][0] = new Rook(GameData::BLACK);

Which is why I cannot make the move method purely virtual.. because the new Piece* call complains that it needs to be implemented.

Upvotes: 2

Views: 821

Answers (2)

Jon
Jon

Reputation: 437684

The compiler is complaining because your Pawn constructor does not specify how its Piece base sub-object should be initialized. Normally not specifying this will result in the default constructor of Piece being called, but Piece does not have a default constructor, hence the error.

Fix it by being explicit:

Pawn::Pawn(GameData::Color _c) : Piece(_c) {}

This tells the compiler that you want to initialize the base by calling the constructor that accepts a Color; that constructor will take care of assigning c = _c so (given the simplified example) you are left with an empty body for Pawn::Pawn.

Incidentally, since you intend to use Piece not only as a base class but also to expose an interface to the outside world, Pawn should derive publicly from Piece.

Upvotes: 5

Paweł Stawarz
Paweł Stawarz

Reputation: 4012

You have to call the Piece constructor via the initialization list:

Pawn(GameData::Color _c): Piece(_c) {}

Or create a default constructor and initialize the values via a method. Your choice.

Upvotes: 5

Related Questions