Online Book Reader

Home Category

Professional C__ - Marc Gregoire [346]

By Root 1342 0
now has two parameters: T and Container. Thus, wherever you previously referred to Grid you must now refer to Grid to specify both template parameters. The only other change is that mCells is now a pointer to a dynamically allocated array of Containers instead of a pointer to a dynamically allocated two-dimensional array of T elements.

Here is the constructor definition. It assumes that the Container type has a resize() method. If you try to instantiate this template by specifying a type that has no resize() method, the compiler will generate an error:

template

Grid::Grid(size_t inWidth, size_t inHeight) :

mWidth(inWidth), mHeight(inHeight)

{

// Dynamically allocate the array of mWidth containers

mCells = new Container[mWidth];

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

// Resize each container so that it can hold mHeight elements.

mCells[i].resize(mHeight);

}

}

Code snippet from GridTemplateContainer\Grid.h

Here is the destructor definition. There’s only one call to new in the constructor, so only one call to delete in the destructor.

template

Grid::~Grid()

{

delete [] mCells;

mCells = nullptr;

}

Code snippet from GridTemplateContainer\Grid.h

The code in copyFrom() assumes that you can access elements in the container by using array [] notation. Chapter 18 explains how to overload the [] operator to implement this feature in your own container classes. Both vector and deque from the STL support this syntax.

template

void Grid::copyFrom(const Grid& src)

{

mWidth = src.mWidth;

mHeight = src.mHeight;

mCells = new Container[mWidth];

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

// Resize each element, as in the constructor.

mCells[i].resize(mHeight);

}

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

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

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

}

}

}

Code snippet from GridTemplateContainer\Grid.h

Here are the implementations of the remaining methods:

template

Grid::Grid(const Grid& src)

{

copyFrom(src);

}

template

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

{

// Check for self-assignment.

if (this == &rhs) {

return *this;

}

// Free the old memory.

delete [] mCells;

mCells = nullptr;

// Copy the new memory.

copyFrom(rhs);

return *this;

}

template

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

{

mCells[x][y] = inElem;

}

template

T& Grid::getElementAt(size_t x, size_t y)

{

return mCells[x][y];

}

template

const T& Grid::getElementAt(size_t x, size_t y) const

{

return mCells[x][y];

}

Code snippet from GridTemplateContainer\Grid.h

Now you can instantiate and use Grid objects like this:

Grid> myIntGrid;

Grid> myIntGrid2;

myIntGrid.setElementAt(3, 4, 5);

cout << myIntGrid.getElementAt(3, 4);

Grid> grid2(myIntGrid);

grid2 = myIntGrid;

Code snippet from GridTemplateContainer\GridTest.cpp

The use of the word Container for the parameter name doesn’t mean that the type really must be a container. You could try to instantiate the Grid class with an int instead:

Grid test; // WILL NOT COMPILE

This line will not compile, but it might not give you the error you expect. It won’t complain that the second type argument is an int instead of a container. Instead it will tell you that left of '.resize' must have class/struct/union type. That’s because the compiler attempts to generate a Grid class with int as the Container. Everything works fine until it tries to compile this line:

mCells[i].resize(mHeight);

At that point, the compiler realizes that mCells[i] is an int, so you can’t call the resize() method on it.

This approach is used in

Return Main Page Previous Page Next Page

®Online Book Reader