Professional C__ - Marc Gregoire [341]
mCells[x][y] = new char[len];
strncpy(mCells[x][y], inElem, len);
}
}
char* Grid { if (mCells[x][y] == nullptr) { return nullptr; } size_t len = strlen(mCells[x][y]) + 1; char* ret = new char[len]; strncpy(ret, mCells[x][y], len); return ret; } Code snippet from GridSpecialization\GridString.h getElementAt() returns a deep copy of the string, so you don’t need an overload that returns a const char*. However, since it does return a deep copy, the caller is responsible to free the memory returned by getElementAt() with delete[]. This section discussed how to use template class specialization. It allows you to write a special implementation for a template with the template types replaced by specific types. The next chapter continues the discussion of specialization with a more advanced feature called partial specialization. Subclassing Template Classes You can write subclasses of template classes. If the subclass inherits from the template itself, it must be a template as well. Alternatively, you can write a subclass to inherit from a specific instantiation of the template class, in which case your subclass does not need to be a template. As an example of the former, suppose you decide that the generic Grid class doesn’t provide enough functionality to use as a game board. Specifically, you would like to add a move() method to the game board that moves a piece from one location on the board to another. Here is the class definition for the GameBoard template: template class GameBoard : public Grid { public: GameBoard(size_t inWidth = Grid size_t inHeight = Grid void move(size_t xSrc, size_t ySrc, size_t xDest, size_t yDest); }; Code snippet from GridSubclass\GameBoard.h This GameBoard template subclasses the Grid template, and thereby inherits all its functionality. You don’t need to rewrite setElementAt(), getElementAt(), or any of the other methods. You also don’t need to add a copy constructor, operator=, or destructor, because you don’t have any dynamically allocated memory in the GameBoard. The dynamically allocated memory in the Grid superclass will be taken care of by the Grid copy constructor, operator=, and destructor. The inheritance syntax looks normal, except that the superclass is Grid Here are the implementations of the constructor and the move() method. Again, note the use of Grid template GameBoard Grid { } template void GameBoard { this->mCells[xDest][yDest] = this->mCells[xSrc][ySrc]; this->mCells[xSrc][ySrc] = T(); // default construct the src cell } Code snippet from GridSubclass\GameBoard.h As you can see, move() uses the syntax T() described in the section on “Method Templates with Non-Type Parameters.” You can use the GameBoard template as follows: GameBoard ChessPiece pawn; chessBoard.setElementAt(0, 0, pawn); chessBoard.move(0, 0, 0, 1); Code snippet from GridSubclass\GameBoardTest.cpp