Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Exercises

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 X with a single constructor that takes an int argument and a member function f( ), which takes no arguments and returns void. Now derive Y and Z from X, creating constructors for each of them that take a single int argument. Next, derive A from Y and Z. Create an object of class A, and call f( ) for that object. Fix the problem with explicit disambiguation.

2.      Starting with the results of Exercise 1, create a pointer to an X called px and assign to it the address of the object of type A you created before. Fix the problem using a virtual base class. Now fix X so you no longer have to call the constructor for X inside A.

3.      Starting with the results of Exercise 2, remove the explicit disambiguation for f( ) and see if you can call f( ) through px. Trace it to see which function gets called. Fix the problem so the correct function will be called in a class hierarchy.

4.      Make an Animal interface class with a makeNoise( ) function declaration. Make a SuperHero interface class with a savePersonFromFire( ) function declaration. Place a move( ) function declaration in both interface classes. (Remember to make your interface methods pure virtual.) Now define three separate classes: SuperlativeMan, Amoeba (a superhero of uncertain gender), and TarantulaWoman; SuperlativeMan implements the SuperHero interface while Amoeba and TarantulaWoman implement both Animal and SuperHero. Define two global functions animalSound(Animal*) and saveFromFire(SuperHero*). Invoke all the methods that are callable from each interface in both of these functions.

5.      Repeat the previous exercise, but use templates instead of inheritance to implement the interfaces, as we did in Interfaces2.cpp.

6.      Define some concrete mixin classes that represent superhero capabilities (such as StopTrain, BendSteel, ClimbBuilding, etc.). Redo exercise 4 so that your derived SuperHero classes derive from these mixins and call their member functions.

7.      Repeat the previous exercise using templates by making your superhero powers mixin template parameters. Use these powers to do some good in the community.

8.      Dropping the Animal interface from exercise 4, redefine Amoeba to only implement SuperHero. Now define a SuperlativeAmoeba class that inherits from both SuperlativeMan and Amoeba. Try to pass a SuperlativeAmoeba object to saveFromFire( ). What do you have to do to make this legal? How does using virtual inheritance change the size of your objects?

9.      Continuing with the previous exercise, add an integer strengthFactor data member to SuperHero from exercise 4, along with a constructor to initialize it. Add constructors in the three derived classes to initialize strengthFactor as well. What must you do differently in SuperlativeAmoeba?

10.    Continuing with the previous exercise, add an eatFood( ) member function to both SuperlativeMan and Amoeba (but not SuperlativeAmoeba), such that the two versions of eatFood( ) take different types of food objects (so the signatures of the two functions differ). What must you do in SuperlativeAmoeba to call either eatFood( ) function? Why?

11.    Define a well-behaved output stream inserter and assignment operator for SuperlativeAmoeba.

12.    Remove SuperlativeAmoeba from your hierarchy and modify Amoeba to derive from both SuperlativeMan (which still derives from SuperHero) and SuperHero. Implement a virtual workout( ) function in both SuperHero and SuperlativeMan (with identical signatures), and call it with a Amoeba object. Which function gets called?

13.    Redefine SuperlativeAmoeba to use composition instead of inheritance to act as a SuperlativeMan or Amoeba. Use conversion operators to provide implicit upcasting. Compare this approach to the inheritance approach.

14.    Suppose you are given a pre-compiled Person class (you only have the header and compiled object file). Suppose also that Person has a non-virtual work( ) function. Have SuperHero be able to act as a mild-mannered ordinary Person by deriving from Person and using the implementation of Person::work( ), but make SuperHero::work( ) virtual.

15.    Define a reference-counted error logging mixin class, ErrorLog, that holds a static file stream to which you can send messages. The class opens the stream when its reference count exceeds 0 and closes the stream when the count returns to 0 (and always appends to the file). Have objects of multiple classes send messages to the static log stream. Watch the stream open and close via trace statements in ErrorLog.

16.    Modify BreakTie.cpp by adding a class named VeryBottom that derives (non-virtually) from Bottom. VeryBottom should look just like Bottom except change Left to Right in the using declaration for f. Change main( ) to instantiate a VeryBottom instead of a Bottom object. Which f( ) gets called?

 


Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire