3

I am building a simple chess application and I've been finding some issues. Here is my problem:

I have a class Piece:

class Piece {
protected:
    std::string name; // this is to store the piece's name (bishop, rook, etc.)
public:
    Piece();
    int positionX;
    int positionY;
    std::string getName();
};

And I also have a class Board, which has a 8x8 matrix of Pieces:

class Board {
public:
    // the construct fills the matrix with instances from Piece just so all matrix slots will have a piece
    Board();
    void showBoard();
    std::vector<std::vector<Piece>> piece;
    void place(Piece piece, char positionY, int positionX);
};

At the moment, I have a board object with 64 generic Pieces.

Now, I created a class Rook, which inherits from Piece:

class Rook: public Piece {
private:
    std::string color;
public:
    Rook(std::string color);
    std::string getColor();
    bool isRook = true; // dummy attribute just to show you my problem
};

And now I try to place my rook inside my pieces matrix:

Board board;
Rook rook = Rook("white");
rook.positionX = 3;
rook.positionY = 0;
board.piece.at(rook.positionX).at(rook.positionY) = rook;

std::cout << board.piece.at(3).at(0).positionX << std::endl; // as expected, this outputs 3

Finally, here comes my actual issue:

When I try to access something that only rook has, and not the other pieces, for example the bool isRook, it throws an error that Piece class has no attribute isRook:

std::cout << board.piece.at(3).at(0).isRook << std::endl; // this throws an error "class Piece has no attribute isRook"

I assume this is because I have a matrix of Pieces, so I can't access things that are specific to Rooks. How can I solve this issue?

Samuel Liew
  • 68,352
  • 105
  • 140
  • 225
zervit
  • 33
  • 1
  • 4

2 Answers2

1

The thing is: Either you use polymorphism or you don't. Something in between is possible but adds complications. Having a container of base class pointers and wanting to access an object as a child class is a design smell. You fix it by providing the method in the base class:

class Piece {
protected:
    std::string name; // this is to store the piece's name (bishop, rook, etc.)
public:
    Piece();
    int positionX;
    int positionY;
    std::string getName();
    bool isRook();                   // all Pieces have a isRook()
    virtual ~Piece();                // virtual destructor !
};

Also note that Piece was missing a virtual destructor. Last but not least you need a vector of pointers to make use of polymorphism. Currently you have object slicing. Read more on that here: Why doesn't polymorphism work without pointers/references?

463035818_is_not_a_number
  • 64,173
  • 8
  • 58
  • 126
1

If you are going to have a polymorphic vector, you need to use a vector of pointers like so:

std::vector<std::vector<Piece*>> piece;

Then you can add different derived objects to the vector like:

piece.push_back(new Rook("white"));
piece.push_back(new Bishop("white"));

You also should use a virtual destructor in the base class:

virtual ~Piece();  

And set the destructor in the board class to handle the new objects accordingly when the board object is destructed:

~Board(){
   for(Piece* p: piece){
      delete p;
   }
}  

Now, this is using raw pointers, maybe a better way to go about it is to use smart pointers.

anastaciu
  • 20,013
  • 7
  • 23
  • 43