Online Book Reader

Home Category

Professional C__ - Marc Gregoire [337]

By Root 1131 0
continue the approach of making height and width template parameters, you might want to be able to provide defaults for the height and width just as you did previously in the constructor of the Grid class. C++ allows you to provide defaults for template parameters with a similar syntax. Here is the class definition:

template

class Grid

{

// Remainder is identical to the previous version

};

Code snippet from GridNonTypeDefault\Grid.h

You do not need to specify the default values for WIDTH and HEIGHT in the template specification for the method definitions. For example, here is the implementation of setElementAt():

template

void Grid::setElementAt(size_t x, size_t y, const T& inElem)

{

mCells[x][y] = inElem;

}

Code snippet from GridNonTypeDefault\Grid.h

Now, you can instantiate a Grid with only the element type, the element type and the width, or the element type, width, and height:

Grid myGrid;

Grid anotherGrid;

Grid aThirdGrid;

Code snippet from GridNonTypeDefault\GridTest.cpp

The rules for default parameters in template parameter lists are the same as for functions or methods: You can provide defaults for parameters in order starting from the right.

Method Templates

C++ allows you to templatize individual methods of a class. These methods can be inside a class template or in a non-templatized class. When you write a templatized class method, you are actually writing many different versions of that method for many different types. Method templates come in useful for assignment operators and copy constructors in class templates.

Virtual methods and destructors cannot be method templates.

Consider the original Grid template with only one parameter: the element type. You can instantiate grids of many different types, such as ints and doubles:

Grid myIntGrid;

Grid myDoubleGrid;

Code snippet from MethodTemplates\GridTest.cpp

However, Grid and Grid are two different types. If you write a function that takes an object of type Grid, you cannot pass a Grid. Even though you know that the elements of an int grid could be copied to the elements of a double grid, because the ints could be coerced into doubles, you cannot assign an object of type Grid to one of type Grid or construct a Grid from a Grid. Neither of the following two lines compiles:

myDoubleGrid = myIntGrid; // DOES NOT COMPILE

Grid newDoubleGrid(myIntGrid); // DOES NOT COMPILE

The problem is that the Grid template copy constructor and operator= prototypes look like this:

Grid(const Grid& src);

Grid& operator=(const Grid& rhs);

The Grid copy constructor and operator= both take a reference to a const Grid. When you instantiate a Grid and try to call the copy constructor and operator=, the compiler generates methods with these prototypes:

Grid(const Grid& src);

Grid& operator=(const Grid& rhs);

Note that there are no constructors or operator= that take a Grid within the generated Grid class. However, you can rectify this oversight by adding templatized versions of the copy constructor and operator= to the Grid class to generate routines that will convert from one grid type to another. Here is the new Grid class definition:

template

class Grid

{

public:

Grid(size_t inWidth = kDefaultWidth, size_t inHeight = kDefaultHeight);

Grid(const Grid& src);

template

Grid(const Grid& src);

virtual ~Grid();

Grid& operator=(const Grid& rhs);

template

Grid& operator=(const Grid& rhs);

// Omitted for brevity

protected:

void copyFrom(const Grid& src);

template

void copyFrom(const Grid& src);

T** mCells;

size_t mWidth, mHeight;

};

Code snippet from MethodTemplates\Grid.h

Member templates do not replace non-template members with the same name. This rule leads to problems with the

Return Main Page Previous Page Next Page

®Online Book Reader