Professional C__ - Marc Gregoire [332]
chessBoard.setPieceAt(0, 0, pawn);
A Template Grid Class
The GameBoard class in the previous section is nice, but insufficient. For example, it’s quite similar to the Spreadsheet class from Chapter 7, but the only way you could use it as a spreadsheet would be to make the SpreadsheetCell class a subclass of GamePiece. That doesn’t make sense because it doesn’t fulfill the is-a principle of inheritance: A SpreadsheetCell is not a GamePiece. It would be nice if you could write a generic Grid class that you could use for purposes as diverse as a Spreadsheet or a ChessBoard. In C++, you can do this by writing a class template, which allows you to write a class without specifying one or more types. Clients then instantiate the template by specifying the types they want to use.
The Grid Class Definition
In order to understand class templates, it is helpful to examine the syntax. The following example shows how you can tweak your GameBoard class slightly to make a templatized Grid class. Don’t let the syntax scare you — it’s all explained following the code. Note that the class name has changed from GameBoard to Grid, and setPieceAt() and getPieceAt() have changed to setElementAt() and getElementAt() to reflect the class’ more generic nature:
template class Grid { public: Grid(size_t inWidth = kDefaultWidth, size_t inHeight = kDefaultHeight); Grid(const Grid virtual ~Grid(); Grid void setElementAt(size_t x, size_t y, const T& inElem); T& getElementAt(size_t x, size_t y); const T& getElementAt(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 Grid T** mCells; size_t mWidth, mHeight; }; Code snippet from Grid\Grid.h Now that you’ve seen the full class definition, take another look at it, one line at a time: template This first line says that the following class definition is a template on one type. Both template and typename are keywords in C++. As discussed earlier, templates “parameterize” types the same way that functions “parameterize” values. Just as you use parameter names in functions to represent the arguments that the caller will pass, you use type names (such as T) in templates to represent the types that the caller will specify. There’s nothing special about the name T — you can use whatever name you want. Traditionally, when a single type is used, it is called T, but that’s just a historical convention, like calling the integer that indexes an array i or j. For historical reasons, you can use the keyword class instead of typename to specify template type parameters. Thus, many books and existing programs use syntax like this: template The template specifier holds for the entire statement, which in this case is the class definition. Several lines further, the copy constructor looks like this: Grid(const Grid As you can see, the type of the src parameter is no longer a const Grid&, but a const Grid