42. Change StlShape.cpp so that it uses a deque instead of a vector.
43. Modify Reversible.cpp so it works with deque and list instead of vector.
44. Use a stack<int> and populate it with a Fibonacci sequence. The program’s command line should take the number of Fibonacci elements desired, and you should have a loop that looks at the last two elements on the stack and pushes a new one for every pass through the loop.
45. Using only three stacks (source, sorted, and losers), sort a random sequence of numbers by placing the numbers initially on the source stack. Assume the number on the top of the source is the largest, and push it on the sorted stack. Continue to pop the source stack comparing it with the top of the sorted stack. Whichever number is the smallest, pop it from its stack and push it onto the on the losers’ stack. Once the source stack is empty, repeat the process using the loser’s stack as the source stack, and use the source stack as the losers’ stack. The algorithm completes when all the numbers have been placed into the winners’ stack.
46. Open a text file whose name is provided on the command line. Read the file a word at a time, and use a multiset<string> to create a word count for each word.
47. Modify WordCount.cpp so that it uses insert( ) instead of operator[ ] to insert elements in the map.
48. Create a class that has an operator< and an ostream& operator<<. The class should contain a priority number. Create a generator for your class that makes a random priority number. Fill a priority_queue using your generator, and then pull the elements out to show they are in the proper order.
49. Rewrite Ring.cpp so it uses a deque instead of a list for its underlying implementation.
50. Modify Ring.cpp so that the underlying implementation can be chosen using a template argument. (Let that template argument default to list.)
51. Create an iterator class called BitBucket that just absorbs whatever you send to it without writing it anywhere.
52. Create a kind of "hangman" game. Create a class that contains a char and a bool to indicate whether that char has been guessed yet. Randomly select a word from a file, and read it into a vector of your new type. Repeatedly ask the user for a character guess, and after each guess, display the characters in the word that have been guessed, and display underscores for the characters that haven’t. Allow a way for the user to guess the whole word. Decrement a value for each guess, and if the user can get the whole word before the value goes to zero, they win.
53. Open a file and read it into a single string. Turn the string into a stringstream. Read tokens from the stringstream into a list<string> using a TokenIterator.
54. Compare the performance of stack based on whether it is implemented with vector, deque, or list.
55. Create a template that implements a singly-linked list called SList. Provide a default constructor and begin( ) and end( ) functions (via an appropriate nested iterator), insert( ), erase( ) and a destructor.
56. Generate a sequence of random integers storing them into an array of int. Initialize a valarray<int> with its contents. Compute the sum, minimum value, maximum value, average, and median of the integers using valarray operations.
57. Create a valarray<int> with 12 random values. Create another valarray<int> with 20 random values. You will interpret the first valarray as a 3 x 4 matrix of ints and the second as a 4 x 5 matrix of ints, and multiply them by the rules of matrix multiplication. Store the result in a valarray<int> of size 15, representing the 3 x 5 result matrix. Use slices to multiply the rows of the first matrix time the columns of the second. Print the result in rectangular matrix form.
[ ]
Part 3: Special Topics
The mark of a professional in any field appears in his or her attention to the finer points of the craft. In this part of the book we discuss advanced features of C++ along with development techniques used by polished C++ professionals.
Once in a great while you may need to depart from the conventional wisdom of sound object-oriented design by inspecting the runtime type of an object for special processing. Most of the time you should let virtual functions do that job for you, but when writing special-purpose software tools, such as debuggers, database viewers, or class browsers, you’ll need to determine type information at runtime. This is where the runtime type identification (RTTI) mechanism comes into play, which is the topic of Chapter 8. Multiple inheritance has taken a bad rap over the years, and some languages don’t even support it. Nonetheless, when used properly, it can be a powerful tool for crafting elegant, efficient code. A number of standard practices involving multiple inheritance have evolved over the years, which we present in Chapter 9. Perhaps the most notable innovation in software development since object-oriented techniques is the use of design patterns. A design pattern describes and presents solutions for many of the common problems involved in designing software, and can be applied in many situations and implemented in any language. In chapter 10 we describe a selected number of widely-used design patterns and implement them in C++. Chapter 11 explains in detail the benefits and challenges of multi-threaded programming. The current version of standard C++ does not specify support for threads, even though most operating systems support them. We use a portable, freely-available thread library to illustrate how C++ programmers can take advantage of threads to build more usable and responsive applications.
8: Runtime type identification
Runtime type identification (RTTI) lets you find the dynamic type of an object when you have only a pointer or a reference to the base type.
This can be thought of as a "secondary" feature in C++, pragmatism to help out when you get into rare messy situations. Normally, you’ll want to intentionally ignore the exact type of an object and let the virtual function mechanism implement the correct behavior for that type automatically. On occasion, however, it’s useful to know the exact runtime (that is, most derived) type of an object for which you only have a base pointer. Often this information allows you to perform a special-case operation more efficiently or prevent a base-class interface from becoming ungainly. It happens enough that most class libraries contain virtual functions to produce run-time type information. When exception handling was added to C++, it required information about the runtime type of objects. It became an easy next step to build access to that information into the language. This chapter explains what RTTI is for and how to use it.