much further. A complicated container-class library may cover all sorts of additional issues, including multithreading, persistence and garbage collection.
Solutions to selected exercises can be found in the electronic document The Thinking in C++ Annotated Solution Guide, available for a small fee from www.BruceEckel.com.
1. Implement the inheritance hierarchy in the OShape diagram in this chapter.
2. Modify the result of Exercise 1 from Chapter 15 to use the Stack and iteratorin TStack2.h instead of an array of Shape pointers. Add destructors to the class hierarchy so you can see that the Shape objects are destroyed when the Stack goes out of scope.
3. Modify TPStash.h so that the increment value used by inflate( )can be changed throughout the lifetime of a particular container object.
4. Modify TPStash.hso that the increment value used by inflate( )automatically resizes itself to reduce the number of times it needs to be called. For example, each time it is called it could double the increment value for use in the next call. Demonstrate this functionality by reporting whenever an inflate( )is called, and write test code in main( .
5. Templatize the fibonacci( function on the type of value that it produces (so it can produce lon , floa , etc. instead of just int).
6. Using the Standard C++ Library vector as an underlying implementation, create a Set template class that accepts only one of each type of object that you put into it. Make a nested iteratorclass that supports the “end sentinel” concept in this chapter. Write test code for your Set in main( , and then substitute the Standard C++ Library set template to verify that the behavior is correct.
780 Thinking in C++ www.BruceEckel.com
7. Modify AutoCounter. so that it can be used as a member object inside any class whose creation and destruction you want to trace. Add a string member to hold the name of the class. Test this tool inside a class of your own.
8. Create a version of OwnerStack. that uses a Standard C++ Library vector as its underlying implementation. You may need to look up some of the member functions of vector in order to do this (or just look at the header file).
9. Modify ValueStack.hso that it dynamically expands as you push( ) more objects and it runs out of space. Change ValueStackTest.cp to test the new functionality.
10. Repeat Exercise 9 but use a Standard C++ Library vector as the internal implementation of the ValueStac . Notice how much easier this is.
11. Modify ValueStackTest.cp so that it uses a Standard C++ Library vector instead of a Stack in main( . Notice the run-time behavior: Does the vector automatically create a bunch of default objects when it is created?
12. Modify TStack2.hso that it uses a Standard C++ Library vector as its underlying implementation. Make sure that you don’t change the interface, so that TStack2Test.cpp works unchanged.
13. Repeat Exercise 12 using a Standard C++ Library stack instead of a vector (you may need to look up information about the stac , or hunt through the header file).
14. Modify TPStash2.hso that it uses a Standard C++ Library vector as its underlying implementation. Make sure that you don’t change the interface, so that TPStash2Test.cpp orks unchanged.
15. In IterIntStack.cpp modify IntStackIter o give it an “end sentinel” constructor, and add operator==and operator! . In main( , use an iterator to move through
16: Introduction to Templates 781
the elements of the container until you reach the end sentinel.
16. Using TStack2.h TPStash2.h and Shape.h instantiate Stack and PStash containers for Shape , fill them each with an assortment of upcast Shape pointers, then use iterators to move through each container and call draw( ) for each object.
17. Templatize the Int class in TPStash2Test.cp so that it holds any type of object (feel free to change the name of the class to something more appropriate).
18. Templatize the IntArray class in IostreamOperatorOverloading.cppom Chapter 12, templatizing both the type of object that is contained and the size of the internal array.
19. Turn ObjContainer n NestedSmartPointer.cpp om Chapter 12 into a template. Test it with two different classes.
20. Modify C15:OStack.hand C15:OStackTest.cpp y templatizing class Stackso that it automatically multiply inherits from the contained class and from Objec . The generated Stack should accept and produce only pointers of the contained type.
21. Repeat Exercise 20 using vector instead of Stac . 22. Inherit a class StringVector rom vector nd
redefine the push_back( ) nd operatormember functions to accept and produce only string*(and perform the proper casting). Now create a template that will automatically make a container class to do the same thing for pointers to any type. This technique is often used to reduce code bloat from too many template instantiations.
23. In TPStash2.h add and test an operator- to PStash::iterator following the logic of operator+
24. In Drawing.cp , add and test a function template to call erase( ) member functions.
782 Thinking in C++ www.BruceEckel.com
25. (Advanced) Modify the Stack class in TStack2.h to allow full granularity of ownership: Add a flag to each link indicating whether that link owns the object it points to, and support this information in the push( ) function and destructor. Add member functions to read and change the ownership for each link.
26. (Advanced) Modify PointerToMemberOperator.cpp from Chapter 12 so that the FunctionObjec and operator->*are templatized to work with any return type (for operator->, you’ll have to use member templates, described in Volume 2). Add and test support for zero, one and two arguments in Dog member functions.
16: Introduction to Templates 783