I can't make chessman an abstract class because I need to create an 2D array of it.
Yes, you can. You don't create an array of chessman
objects, you create an array of pointers to chessman
objects. Then chessman
can be abstract (as it should be, since you should not be creating instances of chessman
directly to begin with).
pawn class inherits chessman and I need to use move function of pawn when I write this
Polymorphism handles that for you. But in order to use an array of polymorphic objects, the array needs to hold pointers/references to objects that are stored elsewhere in memory, not hold the actual objects themselves.
In Java, it's easy since you can create arrays of abstract classes, but in C++ it is just confusing.
You do the exact same thing in C++. In Java, objects are reference types, so they are always referenced by pointer (the Java language simply hides that detail from you).
Try something like this:
class chessman
{
private:
virtual bool isValidMove(string final_pos) = 0;
public:
int i;
int j;
string name;
char color;
chessman(string aname, char acolor);
bool move(string final_pos);
};
chessman::chessman(string aname, char acolor)
: name(aname), color(acolor)
{
}
bool chessman::move(string final_pos)
{
// validate that final_pos is a valid position on the board...
// validate that final_pos is a valid position for the piece being moved...
if (!isValidMove(final_pos))
return false;
// move to the position...
return true;
}
class pawn : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
pawn(string pos, char color);
};
pawn::pawn(string pos, char color)
: chessman("pawn", color)
{
//...
}
bool pawn::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this pawn to move to...
return ...;
}
class rook : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
rook(string pos, char color);
};
rook::rook(string pos, char color)
: chessman("rook", color)
{
//...
}
bool rook::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this rook to move to...
return ...;
}
class knight : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
knight(string pos, char color);
};
knight::knight(string pos, char color)
: chessman("knight", color)
{
//...
}
bool knight::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this knight to move to...
return ...;
}
class bishop : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
bishop(string pos, char color);
};
bishop::bishop(string pos, char color)
: chessman("bishop", color)
{
//...
}
bool bishop::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this bishop to move to...
return ...;
}
class queen : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
queen(string pos, char color);
};
queen::queen(string pos, char color)
: chessman("queen", color)
{
//...
}
bool queen::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this queen to move to...
return ...;
}
class king : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
king(string pos, char color);
};
king::king(string pos, char color)
: chessman("king", color)
{
//...
}
bool king::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this king to move to...
return ...;
}
Then you can do somthing like this:
chessman* white_pieces[16];
chessman* black_pieces[16];
for (int i = 0; i < 8; ++i)
{
white_pieces[i] = new pawn(...);
black_pieces[i] = new pawn(...);
}
for (int i = 8; i < 10; ++i)
{
white_pieces[i] = new rook(...);
black_pieces[i] = new rook(...);
}
for (int i = 10; i < 12; ++i)
{
white_pieces[i] = new knight(...);
black_pieces[i] = new knight(...);
}
for (int i = 12; i < 14; ++i)
{
white_pieces[i] = new bishop(...);
black_pieces[i] = new bishop(...);
}
white_pieces[14] = new queen(...);
black_pieces[14] = new queen(...);
white_pieces[15] = new king(...);
black_pieces[15] = new king(...);
And move them around as needed:
white_pieces[index]->move(pos);
...
black_pieces[index]->move(pos);
And of course, don't forget to cleanup when you are done:
for (int i = 0; i < 16; ++i)
{
delete white_pieces[i];
delete black_pieces[i];
}
To make the cleanup automatic, you can use an array of std::auto_ptr<chessman>
objects. Or, in C++11 and later, a std::vector
/std::array
of std::unique_ptr<chessman>
objects.