Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |
Solutions
to selected exercises can be found in the electronic document The Thinking
in C++ Volume 2 Annotated Solution Guide, available for a small fee from www.MindView.net.
1. Create a Base class with a virtual destructor and a
Derived class that inherits from Base. Create a vector of Base
pointers that point to Base and Derived objects randomly. Using the
contents your vector, fill a second vector with all the Derived
pointers. Compare execution times between typeid( ) and dynamic_cast
to see which is faster.
2. Modify C16:AutoCounter.h in Volume 1 of this book so that
it becomes a useful debugging tool. It will be used as a nested member of each
class that you are interested in tracing. Turn AutoCounter into a
template that takes the class name of the surrounding class as the template
argument, and in all the error messages use RTTI to print the name of the
class.
3. Use RTTI to assist in program debugging by printing out the exact
name of a template using typeid( ). Instantiate the template for
various types and see what the results are.
4. Modify the Instrument hierarchy from Chapter 14 of Volume
1 by first copying Wind5.cpp to a new location. Now add a virtual clearSpitValve( )
function to the Wind class, and redefine it for all the classes
inherited from Wind. Instantiate a vector to hold Instrument
pointers, and fill it with various types of Instrument objects created
using the new operator. Now use RTTI to move through the container
looking for objects in class Wind, or derived from Wind. Call the
clearSpitValve( ) function for these objects. Notice that it would
unpleasantly confuse the Instrument base class if it contained a clearSpitValve( )
function.
5. Modify the previous exercise to place a prepareInstrument( )
function in the base class, which calls appropriate functions (such as clearSpitValve( ),
when it fits). Note that prepareInstrument( ) is a sensible
function to place in the base class, and it eliminates the need for RTTI in the
previous exercise.
6. Create a vector of pointers to 10 random Shape
objects (at least Squares and Circles, for example). The draw( )
member function should be overridden in each concrete class to print the
dimensions of the object being drawn (the length or the radius, whichever
applies). Write a main( ) program that draws all the Squares
in your container first, sorted by length, and then draws all Circles,
sorted by radius.
7. Create a large vector of pointers to random Shape
objects. Write a non-virtual draw( ) function in Shape that
uses RTTI to determine the dynamic type of each object and executes the
appropriate code to draw the object with a switch statement. Then rewrite
your Shape hierarchy the right way, using virtual functions. Compare
the code sizes and execution times of the two approaches.
8. Create a hierarchy of Pet classes, including Dog, Cat,
and Horse. Also create a hierarchy of Food classes: Beef, Fish,
and Oats. The Dog class has a member function, eat( ),
that takes a Beef parameter, likewise, Cat::eat( ) takes a Fish
object, and Oats objects are passed to Horse::eat( ). Create
a vector of pointers to random Pet objects, and visit each Pet,
passing the correct type of Food object to its eat( )
function.
9. Create a global function named drawQuad( ) that takes
a reference to a Shape object. It calls the draw( ) function
of its Shape parameter if it has four sides (that is, if it s a Square
or Rectangle). Otherwise, it prints the message Not a quadrilateral .
Traverse a vector of pointers to random Shapes, calling drawQuad( )
for each one. Place Squares, Rectangles, Circles and Triangles
in your vector.
10. Sort a vector of random Shape objects by class
name. Use type_info::before( ) as the comparison function for
sorting.