|
|
|
|
Exercises
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.
- Modify Car.cpp so
that it also inherits from a class called Vehicle, placing appropriate
member functions in Vehicle (that is, make up some member functions). Add
a nondefault constructor to Vehicle, which you must call inside
Car’s
constructor.
- Create
two classes, A and B, with default constructors that announce
themselves. Inherit a new class called C from A, and create a
member object of B in C, but do not create a constructor for
C. Create an object of class C and observe the
results.
- Create a
three-level hierarchy of classes with default constructors, along with
destructors, both of which announce themselves to cout. Verify
that for an object of the most derived type, all three constructors and
destructors are automatically called. Explain the order in which the calls are
made.
- Modify
Combined.cpp to add another level of inheritance and a new member object.
Add code to show when the constructors and destructors are being
called.
- In
Combined.cpp, create a class D that inherits from B and has
a member object of class C. Add code to show when the constructors and
destructors are being
called.
- Modify
Order.cpp to add another level of inheritance Derived3 with member
objects of class Member4 and Member5. Trace the output of the
program.
- In
NameHiding.cpp, verify that in Derived2, Derived3, and
Derived4, none of the base-class versions of f( ) are
available.
- Modify
NameHiding.cpp by adding three overloaded functions named
h( ) to Base, and show that redefining one of them in a
derived class hides the
others.
- Inherit a
class StringVector from vector<void*> and redefine the
push_back( ) and operator[] member functions to accept and
produce string*. What happens if you try to push_back( ) a
void*?
- Write
a class containing a long and use the psuedo-constructor call syntax in
the constructor to initialize the
long.
- Create
a class called Asteroid. Use inheritance to specialize the
PStash class in Chapter 13 (PStash.h & PStash.cpp) so
that it accepts and returns Asteroid pointers. Also modify
PStashTest.cpp to test your classes. Change the class so PStash is
a member
object.
- Repeat
Exercise 11 with a vector instead of a
PStash.
- In
SynthesizedFunctions.cpp, modify Chess to give it a default
constructor, copy-constructor, and assignment operator. Demonstrate that
you’ve written these
correctly.
- Create
two classes called Traveler and Pager without default
constructors, but with constructors that take an argument of type string,
which they simply copy to an internal string variable. For each class,
write the correct copy-constructor and assignment operator. Now inherit a class
BusinessTraveler from Traveler and give it a member object of type
Pager. Write the correct default constructor, a constructor that takes a
string argument, a copy-constructor, and an assignment
operator.
- Create a
class with two static member functions. Inherit from this class and
redefine one of the member functions. Show that the other is hidden in the
derived class.
- Look
up more of the member functions for ifstream. In FName2.cpp, try
them out on the file
object.
- Use
private and protected inheritance to create two new classes from a
base class. Then attempt to upcast objects of the derived class to the base
class. Explain what
happens.
- In
Protected.cpp, add a member function in Derived that calls the
protected Base member
read( ).
- Change
Protected.cpp so that Derived is using protected
inheritance. See if you can call value( ) for a Derived
object.
- Create a
class called SpaceShip with a fly( ) method. Inherit
Shuttle from SpaceShip and add a land( ) method.
Create a new Shuttle, upcast by pointer or reference to a
SpaceShip, and try to call the land( ) method. Explain the
results.
- Modify
Instrument.cpp to add a prepare( ) method to
Instrument. Call prepare( ) inside
tune( ).
- Modify
Instrument.cpp so that play( ) prints a message to
cout, and Wind redefines play( ) to print a different
message to cout. Run the program and explain why you probably
wouldn’t want this behavior. Now put the virtual keyword (which you
will learn about in Chapter 15) in front of the play( ) declaration
in Instrument and observe the change in the
behavior.
- In
CopyConstructor.cpp, inherit a new class from Child and give it a
Member m. Write a proper constructor,
copy-constructor, operator=, and operator<< for
ostreams, and test the class in
main( ).
- Take
the example CopyConstructor.cpp and modify it by adding your own
copy-constructor to Child without calling the base-class
copy-constructor and see what happens. Fix the problem by making a proper
explicit call to the base-class copy constructor in the constructor-initializer
list of the Child
copy-constructor.
- Modify
InheritStack2.cpp to use a vector<string> instead of a
Stack.
- Create
a class Rock with a default constructor, a copy-constructor, an
assignment operator, and a destructor, all of which announce to cout that
they’ve been called. In main( ), create a
vector<Rock> (that is, hold Rock objects by value) and add
some Rocks. Run the program and explain the output you get. Note whether
the destructors are called for the Rock objects in the vector. Now
repeat the exercise with a vector<Rock*>. Is it possible to create
a
vector<Rock&>?
- This
exercise creates the design pattern called proxy. Start with a base class
Subject and give it three functions: f( ), g( ),
and h( ). Now inherit a class Proxy and two classes
Implementation1 and Implementation2 from Subject.
Proxy should contain a pointer to a Subject, and all the member
functions for Proxy should just turn around and make the same calls
through the Subject pointer. The Proxy constructor takes a pointer
to a Subject that is installed in the Proxy (usually by the
constructor). In main( ), create two different Proxy objects
that use the two different implementations. Now modify Proxy so that you
can dynamically change
implementations.
- Modify
ArrayOperatorNew.cpp from Chapter 13 to show that, if you inherit from
Widget, the allocation still works correctly. Explain why inheritance in
Framis.cpp from Chapter 13 would not work
correctly.
- Modify
Framis.cpp from Chapter 13 by inheriting from Framis and creating
new versions of new and delete for your derived class. Demonstrate
that they work
correctly.
[51]
In Java, the compiler won’t let you decrease the access of a member during
inheritance.
[52]
To learn more about this idea, see Extreme Programming Explained, by Kent
Beck (Addison-Wesley 2000).
[53]
See Refactoring: Improving the Design of Existing Code by Martin Fowler
(Addison-Wesley 1999).
|
|
|