Online Book Reader

Home Category

Professional C__ - Marc Gregoire [331]

By Root 1060 0
for each game from the GamePiece class. For example, in the chess game, the ChessPiece would be a subclass of GamePiece. Through polymorphism, the GameBoard, written to store GamePieces, can also store ChessPieces. Your class definition might look similar to the Spreadsheet class from Chapter 7, which used a dynamically allocated two-dimensional array as the underlying grid structure:

class GameBoard

{

public:

// The general-purpose GameBoard allows the user to specify its dimensions

GameBoard(size_t inWidth = kDefaultWidth,

size_t inHeight = kDefaultHeight);

GameBoard(const GameBoard& src); // Copy constructor

virtual ~GameBoard();

GameBoard& operator=(const GameBoard& rhs); // Assignment operator

void setPieceAt(size_t x, size_t y, const GamePiece& inPiece);

GamePiece& getPieceAt(size_t x, size_t y);

const GamePiece& getPieceAt(size_t x, size_t y) const;

size_t getHeight() const { return mHeight; }

size_t getWidth() const { return mWidth; }

static const size_t kDefaultWidth = 10;

static const size_t kDefaultHeight = 10;

protected:

void copyFrom(const GameBoard& src);

// Objects dynamically allocate space for the game pieces.

GamePiece** mCells;

size_t mWidth, mHeight;

};

Code snippet from GameBoard\GameBoard.h

getPieceAt() returns a reference to the piece at a specified spot instead of a copy of the piece. The GameBoard serves as an abstraction of a two-dimensional array, so it should provide array access semantics by giving the actual object at an index, not a copy of the object. Returning a reference from getPieceAt() works perfectly in this example. However, you should be careful when you write a method that returns something by reference, to make sure the reference stays valid. For example, if the GameBoard class would support a resize() method, this method would reallocate memory for mCells. By doing this, all references previously returned from getPieceAt() would become invalid. So, client code should not store such a reference for future use, but should call getPieceAt() right before using the returned reference.

This implementation of the class provides two versions of getPieceAt(), one of which returns a reference and one of which returns a const reference.

Here are the method definitions. The implementation is almost identical to the Spreadsheet class from Chapter 7. Production code would, of course, perform bounds checking in setPieceAt() and getPieceAt(). That code is omitted because it is not the point of this chapter:

GameBoard::GameBoard(size_t inWidth, size_t inHeight) :

mWidth(inWidth), mHeight(inHeight)

{

mCells = new GamePiece* [mWidth];

for (size_t i = 0; i < mWidth; i++) {

mCells[i] = new GamePiece[mHeight];

}

}

GameBoard::GameBoard(const GameBoard& src)

{

copyFrom(src);

}

GameBoard::~GameBoard()

{

// Free the old memory

for (size_t i = 0; i < mWidth; i++) {

delete [] mCells[i];

}

delete [] mCells;

mCells = nullptr;

}

void GameBoard::copyFrom(const GameBoard& src)

{

mWidth = src.mWidth;

mHeight = src.mHeight;

mCells = new GamePiece* [mWidth];

for (size_t i = 0; i < mWidth; i++) {

mCells[i] = new GamePiece[mHeight];

}

for (size_t i = 0; i < mWidth; i++) {

for (size_t j = 0; j < mHeight; j++) {

mCells[i][j] = src.mCells[i][j];

}

}

}

GameBoard& GameBoard::operator=(const GameBoard& rhs)

{

// Check for self-assignment

if (this == &rhs) {

return *this;

}

// Free the old memory

for (size_t i = 0; i < mWidth; i++) {

delete [] mCells[i];

}

delete [] mCells;

mCells = nullptr;

// Copy the new memory

copyFrom(rhs);

return *this;

}

void GameBoard::setPieceAt(size_t x, size_t y, const GamePiece& inElem)

{

mCells[x][y] = inElem;

}

GamePiece& GameBoard::getPieceAt(size_t x, size_t y)

{

return mCells[x][y];

}

const GamePiece& GameBoard::getPieceAt(size_t x, size_t y) const

{

return mCells[x][y];

}

Code snippet from GameBoard\GameBoard.cpp

This GameBoard class works pretty well. Assuming that you wrote a ChessPiece class, you can create GameBoard objects and use them like this:

GameBoard chessBoard(8, 8);

ChessPiece

Return Main Page Previous Page Next Page

®Online Book Reader