Rob Eiben is an experienced designer and writer of data acquisition software. He received undergraduate training at the Massachusetts Institute of Technology in digital electronics and hardware level programming. He is currently a consultant developing a bar-code data acquisition system under 0S/2. He can be reached at reiben@vt.edu.
Introduction
In his preface, Holub reveals the first version of this book's title: A Curmudgeon's Guide to C++. That turns out to be a pretty good synopsis. His viewpoint is that of an experienced C programmer who desires above all to produce effective and maintainable code. He seeks to exploit the benefits of object-oriented technology and C++ without succumbing to their deficiencies. In keeping with that viewpoint, Holub adopts a down-to-earth style throughout the book, in which he explains a construct of C++, lists its benefits, lists its problems, and provides guildelines to its proper use. This approach is an effective way to teach C++.
Contents
The book consists of seven chapters and an appendix:1. Object-Oriented Programming in C
2. C++: Small Differences from C
3. Simple Classes
4. Operator Overloading
5. Derivation
6. Polymorphism and Virtual Functions
7. An Example Class Library
A. Exception HandlingThe first chapter provides an in-depth look at using object-oriented techniques in ANSI C. It is here that Holub expands upon his ideas about maintainable code and along the way discusses many of the building blocks of object-oriented programming: classes, methods, inheritance, polymorphism, and virtual functions. His idea here is to not overwhelm you with learning a new paradigm and a new notation at the same time, so he teaches the object-oriented ideas using familiar C. In addition, he shows some of the drawbacks of using C for object-oriented programming, preparing you for the solutions C++ will offer.
The second chapter describes those aspects of C++ that are but small variations of C, including the scope operator, the new uses of const, the new and delete operators, function overloading, and references. Here Holub also discusses iostreams, the C++ I/O stream library. He flatly advises against using iostreams, primarily because it provides non-arithmetic functionality by overloaded arithmetic operators (<< and >>) and because its formatted output is hard to construct and read. Even if you disagree with Holub, you will always know where he stands. If you believe in "C++, right or wrong" you will be quite disappointed by this and other sections of the book. Holub calls codes as he sees it, referring to areas of poor maintainability as "brain-damaged syntax."
Chapters 3 through 6 provide a detailed study of those areas where C++ differs the most from C. These chapters provide the meat of the book and explain not only how C++ implements classes, overloaded operators, derivation, and polymorphism, but how best to use these features. In these chapters, Holub also points out aspects of C++ that might be confusing to a C programmer. He also illustrates those constructs that are detrimental to maintainable code. Such constructs, when used improperly, make C++ what he calls a "write-only language." These sections of the book mirror the progression in Chapter 1 so that the concepts of object-oriented development are reinforced.
Chapter 7 walks through the design of a complete class library in C++ using all the techniques taught elsewhere in the book. It is here that Holub also discusses template classes. During the library's construction he works through design decisions that go into many large C++ applications, such as whether to use templates or derivation, and where to draw the line between ease-of-use and maintainability.
The appendix, on exception handling, first describes some of the more common methods of error handling and shows how these are deficient when dealing with constructors and destructors. Holub then explains the exception-handling functions (still "experimental" at the time of the book's writing). He maintains that exceptions should only be used "when a function cannot return an error status in the normal way."
Most Useful Topic
Probably the best section of the book is the section in Chapter 3 on constructors. Holub discusses default constructors, copy constructors, operator= overloads, and type-conversion constructors. Besides explaining the constructors, he describes how the compiler will use them and the problems that can cause. For example, the copy constructor copies an object into uninitialized memory. This affects how you code the constructor. However, the compiler uses the operator= overload to copy an object into initialized memory. Understanding this difference will help you avoid memory leaks and other hard-to-find problems.In this chapter, Holub also shows how C++ builds temporary variables when evaluating an expression. The compiler uses an object's constructors to build these temporaries. This results in subtle errors when a constructor is missing.
In a later chapter on derivation, Holub discusses the use of constructors with classes that have instance variables or classes that are derived. Here he illustrates the purpose of member initialization lists, and we get a couple more rules of thumb:
1. All classes that have instance variables should have a copy constructor that lists all of the instance variables in its member-initialization lists.
2. All derived classes should have a copy constructor that chains to the copy constructors of all base classes in their member-initialization lists.
Explanatory Style
A good example of Holub's style is the section in Chapter 2 covering references. He first describes a reference as a name alias and gives several examples of its usage. Then, because C programmers tend to want to see inside a construct, he goes to some length to explain that a reference is not a pointer, even though the compiler may implement it that way. "A reference is a reference a name alias not a pointer. C programmers tend to think that references must be implemented as pointers, so should be treated as such, and that way lies madness."After describing reference arguments, Holub points out a drawback in their use. C passes arguments by value, which guarantees that the value passed will not be modified by the function. If you want the function to modify your variable, you pass the address explicitly. With a reference, nothing in the function call tips you off that a pass by reference is being made. (We're talking about a real project, where the function prototype is buried in a header file far from the code you are viewing.) To minimize errors, Holub lists a few rules to follow when using references:
1. A function that needs to modify an object in the calling function should be passed a pointer to that object, not a reference.
2. References should be used only for passing around large objects.
These rules illustrate what Holub does so well. He explains a construct in terms of the C programmer's own language, lists the benefits in using it, describes any deficiencies in maintainability, and provides rules of thumb to avoid these deficiencies.
Conclusion
Since the book dates from 1992 it does not cover some of the new constructs being added by the ANSI C++ committee. I would like to see an update covering templates, name spaces, and the new cast operators. In addition, since the book was written, many compilers have included more efficient schemes for implementing exceptions. I'd be curious to hear Holub's opinion on exceptions now.One thing is certain Holub is never ambiguous when expressing his opinions about C++. You may not agree with all he says, but for every rule of thumb he provides several pages of background reasoning. There is always enough information for you to experiment with a compiler and come to your own conclusions. I have found Holub's recommendations essential in the design of a medium-sized C++ application. If you are interested in writing maintainable code, you might too.
Title: C+C++: Programming With Objects in C and C++
Author: Allen I. Holub
Publisher: McGraw-Hill
Pages: 427
Price: $24.95
ISBN: 0-07-029662-6