Search code examples
c++multiple-inheritancediamond-problem

c++ diamond inheritance construct only by base constructor


enter image description here

I have trouble to construct my queen class from using the piece, which is the base class, i had virtual my rook and bishop class, to prevent duplicate problem. right now i got the error stated the Rook and Bishop is virtual and it don't have a default constructor.

here my class declartion

class Piece
{
public:
  Piece(Colour c, const Position& pos);
  virtual ~Piece();
private:
  Colour piece_colour;
  Position piece_pos;
};
class Bishop: public virtual Piece
{
public:
  Bishop(Colour c, const Position& pos);
  ~Bishop();
};

class Rook: public virtual Piece
{
public:
  Rook(Colour c, const Position& pos);
  ~Rook();
};

#ifdef MSC_VER
class Queen: public virtual Piece, public Bishop, public Rook
#else
class Queen: public Bishop, public Rook
#endif
{
public:
  Queen(Colour c, const Position& pos);
  ~Queen();
};

here is my implement

Piece::Piece(Colour c, const Position& pos)
:piece_colour{c}, piece_pos{pos}
{

}

Bishop::Bishop(Colour c, const Position& pos)
:Piece(c,pos)
{

}

Rook::Rook(Colour c, const Position& pos)
:Piece(c,pos)
{

}

Queen::Queen(Colour c, const Position& pos)
:Piece(c,pos)
{

}

Solution

  • Remember that when you construct a Queen object, that object incorporates a Rook object and a Bishop object. Both of those objects also have to be constructed when the Queen object is constructed.

    As your code is currently written, the compiler will try to call the default constructors Bishop() and Rook() to instantiate those objects.

    But your code does not define the Bishop() and Rook() constructors - so you get an error telling you the Bishop and Rook classes don't have default constructors defined.

    One way to address your problem would be to define the default constructors Bishop() and Rook() along with the default constructor Piece()...

    protected:
       Piece::Piece()   { }
       Bishop::Bishop() { }
       Rook::Rook()     { }
    

    … if you do that, you'll want to make those constructors protected so they can only be called from derived classes.

    Another approach would be to change the Queen constructor to explicitly call the Bishop and Rook constructors that you have already defined...

    Queen::Queen(Colour c, const Position& pos)
       : Bishop(c, pos), Rook(c, pos), Piece(c, pos)
    

    If your Bishop(c, pos) and Rook(c, pos) constructors do real work then this second approach is the only real solution (assuming the real work depends on the Colour and Position parameters passed to them).