0
class Bishop : public ChessPiece {
    public:
    friend class Queen;
    Bishop(string colorIn, string nameIn);

    //isLegalMove for bishop
    //implemented this function for queen
    bool isLegalBishopMove(int xSrc, int ySrc, int xDest, int yDest);

    //Can move along any diagnol
    virtual bool isLegalMove(int xSrc, int ySrc, int xDest, int yDest) ;
};


class Queen : public ChessPiece {
 public:
    //friend class Bishop;

    Queen(string colorIn, string nameIn);
    //friend bool Bishop::isLegalBishopMove(int xSrc, int ySrc, int xDest, int yDest);

    virtual bool isLegalMove(int xSrc, int ySrc, int xDest, int yDest);
};

I want my Queen's class implementation of isLegalMove to be able to call the function isLegalBishopMove. How can I solve this? I tried using friend but it did not work. I am not understanding the c++ references.

Andrea Dusza
  • 2,080
  • 3
  • 18
  • 28
  • 1
    Maybe use a middle class: `class Diagnol_Mover : public ChessPiece; class Queen : public Diagnol_Mover;`. – Thomas Matthews Jan 04 '16 at 02:51
  • Honestly, the "logic" for each chess piece is the same, the only difference is where they can move, which is data. I'd use an enumeration rather than subclasses. – Mooing Duck Jan 04 '16 at 03:04
  • @MooingDuck: that's sound advice if there's no computer analysis required, but if there is there could be different logic to evaluate how advantageous/dangerous the piece's position is, to pick the best couple moves possible with that piece etc.. Still, Benjamin's unlikely to be implementing something that complicate anytime soon if he's getting his head around the modelling issues in this question.... – Tony Delroy Jan 04 '16 at 03:46

3 Answers3

5

I would think there is nothing wrong in free functions or public static methods. I prefer them to inheritance.

static bool Queen::isLegalMove(Position poscurr, Position posnew)

static bool Bishop::isLegalMove(Position poscurr, Position posnew)
Aaditya Kalsi
  • 1,039
  • 8
  • 16
2

You can't call a transverse method in a hierarchy of classes. If Queen is not a subclass of Bishop then trying to call a method of Bishop class doesn't make any sense, friend directive can't help here since you are trying to add the behavior of a class definition by including behavior from another class which is not directly related to the former.

I see two possible solutions:

  • make the method static so that you can call it freely from any context
  • use multiple virtual inheritance

The second approach would be something like the following, but I discourage considering this since multiple inheritance has its caveats and must be fully understood before attempting its use.

class ChessPiece
{
   virtual bool isLegalMove(int xSrc, int ySrc, int xDest, int yDest) = 0;
};

class Rook : public ChessPiece {
 ...
};

class Bishop : public ChessPiece {
 ...
};

class Queen : public virtual Rook, public virtual Bishop {
  bool isLegalMove(int xSrc, int ySrc, int xDest, int yDest) override {
    return Bishop::isLegalMove(xSrc,ySrc,xDest,yDest) || Rook::isLegalMove(xSrc, ySrc,xDest,yDest);
  }
};

Mind that passing the source position of the move to isLegalMove doesn't make much sense in an object-oriented environment, the source position should be contained in the ChessPiece instance unless you are using the object hierarchy just to implement behavior (and not pieces state).

Tas
  • 7,023
  • 3
  • 36
  • 51
Jack
  • 131,802
  • 30
  • 241
  • 343
  • The source position of each piece is held in a board object of the ChessBoard class – Benjamin Erichsen Jan 04 '16 at 04:43
  • Although the most innate way to model a chessboard is to have a bidimensional array of cells that's not the only way to do it. You could easily have a `std::vector` and forget about the chess board at all. Or a `std::unordered_map, ChessPiece>` if you need fast lookup. Or even a vector backed by a bidimensonal array of pointers. Solutions are many. – Jack Jan 04 '16 at 04:48
1

You can have Queen::isLegalMove use Bishop::isLegalMove - and presumably Castle's - as follows:

virtual bool isLegalMove(int xSrc, int ySrc, int xDest, int yDest)
{
    return Bishop().isLegalMove(xSrc, ySrc, xDest, yDest) ||
           Rook().isLegalMove(xSrc, ySrc, xDest, yDest);
}

A few points:

  • these functions obviously (to anyone who knows even a little chess), don't need to know anything else about the Queen piece on which they're invoked, so from that perspective they could be static, but then they couldn't be called using virtual dispatch, which you seem to want to do and which might genuinely help keep your code simple

    • that the functions don't take a Board object - to check for pieces in the way of the requested move - implies Board is available as a global or singleton; that's discouraged in programming generally, as it makes it hard to do things like create a tree of Boards you could reach in a fixed number of moves, to assess which move a "computer" player should make
  • I recommend against publicly deriving Queen from Bishop or other pieces that it's not - try to preserve an "is a" relationship for public derivation; "Queen is a (type of) Bishop" is simply not true and could cause unintended trouble later as your logic for Bishops unintentionally affects Queens

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Just FYI, it's called a Rook, not a "Castle" – NoseKnowsAll Jan 04 '16 at 03:08
  • @NoseKnowsAll: by you perhaps; in Australia at least, "castle" is as often used, so I'll use that. – Tony Delroy Jan 04 '16 at 03:13
  • Actually, by the international chess syndicates. See for instance the ICC or FIDE. That being said, you and your friends can call it whatever you like. But on an international site like this it makes sense to call it a Rook. (sorry for nitpicking :/ ) – NoseKnowsAll Jan 04 '16 at 03:21
  • @NoseKnowsAll: ok then - thanks for the insight. Cheers. – Tony Delroy Jan 04 '16 at 03:35
  • @TonyD All the pieces derive from an abstract virtual class called ChessPiece. My life would probably be simpler if isLegalMove wasn't virtual because then I could make it static. However, based on the books I've read, it is proper OO design to use the ChessPiece abstract virtual class since they all have this function. – Benjamin Erichsen Jan 04 '16 at 04:42
  • @BenjaminErichsen: well, having the function virtual can make it simpler if say someone identifies board coordinates to move to and from: just check `board[i][j].isLegalMove(xSrc, ySrc, xDest, yDest)` (you could have an `NoPiece` class implemenent `ChessPiece` for empty board positions, with `isLegalMove` always returning `false`). If you used `static`, you'd need some kind of `switch` statement on all the possible types: a bit ugly. Either can work though: best to pick one and get the overall functionality going then explore code changes for elegance. – Tony Delroy Jan 04 '16 at 04:48
  • I really like the NoPiece Idea – Benjamin Erichsen Jan 04 '16 at 05:13
  • @BenjaminErichsen: it's actually even simpler to have `ChessPiece` itself not be abstract (i.e. no pure virtual functions with `= 0`), with a definition of `isLegalMove` therein that returns `false`, but whichever tickles your fancy. Cheers. (Separately, all your `isLegalMove` functions should probably be `const`, if they're not made `static` and aren't actually changing anything in the object they're invoked on). – Tony Delroy Jan 04 '16 at 05:27