When OOP and C++ were still new to the mainstream, there emerged a tremendous
need on the part of programmers for books on C++. Five years or so ago,
a familiar question in online forums was, "I want to learn more about
C++, where do I start?" It's a sign of the times (as well as of the
decade we live in) that today, the question often is, "I'll be laid
off next month unless I learn C++, where do I start? "
In response to this perceived need, book publishers unleashed a mountain
of books on C++. A search through the Computer Literacy bookstore Web site
(http://www.clbooks.com) now
returns 376 books with C++ in the title. Leafing
through a few of these books, you'll notice that some bear the earmarks
of haste: superficial coverage of the topic, example code that will not
compile, sundry misconceptions, and nuggets of misinformation. On occasion,
it seems that the author is only a few weeks ahead of the reader in grasping
the subject.
Some time ago, Andrew Schulman suggested a useful rule of thumb in weeding
out the Johnny-come-lately novices from dyed-in- the-wool mavens: Consider
only titles whose authors worked at or were once affiliated with Bell Labs.
This filter would include worthwhile books by Bjarne Stroustrup, Margaret
Ellis, Stan Lippman, Rob Murray, Jim Coplien, Stephen Dew-hurst, Kathy Stark,
Andrew Koenig, Tom Cargill, Jonathan Shapiro and Martin Carroll, which should
be plenty.
The premise behind this rule is that C++ is a complex enough subject that
only someone with years of hands-on experience can contribute useful advice,
and for a long time, the only place one could get this experience was at
Bell Labs. Obviously, this premise is less valid as C++ becomes more entrenched
in the mainstream; even in times past, the stringent rule may have slighted
some illuminating introductory treatments by outsiders. Nevertheless, I've
found Schulman's suggestion useful when approaching a bookstores sagging
shelves.
More recently, I've been considering a different rule of thumb: Never read
anything you can't lift. Okay, I've had to break this rule, but let me explain
its rationale.
There's been an arms race among book publishers to make titles as physically
wide as possible, to garner every last inch of shelf space and edge out
competitors. This has resulted in overweight tomes of 800 pages or more,
usually specific to a particular compiler or operating system, often released
within a few weeks of the compiler's initial shipment, yet claiming to be
the last word on the subject. Too often, you find inside a rehash of the
vendor documentation, some toy programs, a few homilies, and well-worn bits
of advice. The tips and suggestions therein take everything at face value,
with little attempt to go beyond the manufacturer's feature list; there
are few of the hard-won lessons that only extensive experience can provide.
As a result, I'm drawn to slim books that carry more than their weight in
knowledge and insight -- classics such as Scott Meyers' Effective C++
(Addison-Wesley, 1992), or James Coplien's Advanced C++ Programming Styles
and Idioms (Addison-Wesley, 1992). These books cover material less likely
to become obsolete with a new version of a particular compiler. C++ beginners
have for a long time been well served by Stan Lippmann's C++ Primer
(Addison-Wesley, 1991) and Stephen Dewhurst and Kathy Stark's Programming
in C++, Second Edition (Prentice-Hall, 1995). These four books together
take up about the same shelf space as one overweight, underpowered title.
However, C++ continues to advance, and more programmers are involved in
multiperson projects whose codebase evolves over time. Once youve learned
the syntax and some language tips, object-oriented design becomes more of
a concern. One recently released book that satisfies a range of needs is
Mastering Object-Oriented Design in C++, by Cay Horstmann. The book
lives up to its billing on the jacket: Everything you need in one manageable
package! In this small-format volume, Horstmann provides both an introduction
to the C++ language and a mini-methodology for object-oriented design that
emphasizes tractable, real-world use instead of the ivory-tower overkill
that some methodologies promote.
Horstmann is a man of few words, and he has packed just about every page
in this book with useful information. The brevity is refreshing, and the
clean and concise approach contrasts favorably with more-weighty tomes.
For example, one popular C++ book has a 60-page chapter on pointers that
begins around page 400. Horstmann dispenses with the subject in all of two
pages. There are no long-winded explanations, drawn-out examples, padding
of the book with page after page of repetitive listings, or half-page diagrams
fluffed up with the currently fashionable 3-D, graduated-tint screens. The
graphic design is as efficient and precise as the prose. There are many
code fragments, usually two or three per page, woven naturally into the
fabric of the discussion. Horstmanns book covers features recently added
to C++, including exceptions, templates, namespaces, and run-time type.
This coverage is not tacked on at the end, but is clearly part of the author's
coding repertoire.
Horstmann makes his points in a no-nonsense fashion that is sometimes opinionated
but whose opinions carry the weight of experience. For example, when talking
about adding new operations to an existing class implementation: "Public
data and cluttered interfaces must be avoided. You have no good choice but
to stop coding your immediate task and to reexamine the overall class design."
Every chapter ends with a list of design hints: "Don't pollute the
global namespace with constants," "A class that has a destructor
needs both a copy constructor and an assignment operator," "Beware
of constructors with a single integer argument," and "Class types
are the norm; challenge basic types." These epigrams are followed by
a one- or two-paragraph explanation.
Horstmann meticulously adheres to a coding style that stays away from a
good number of C++ features I consider of marginal value (such as private
inheritance or pointers to member functions). He acknowledges that coding
preferences can be a matter of intense debate, and provides a 20-page appendix
that lays out the guidelines formally so that you can modify them for personal
or local taste.
If he sounds like a stern schoolmaster, perhaps that's because he is. Horstmann
teaches computer science at San Jose State University in California, and
this book has been designed for classroom teaching as well as personal use.
Every chapter has exercises that go beyond the rote repetition you may have
encountered in school. For example, Exercise 13.1.1 is: "Try corrupting
the free list on purpose to see what happens on your system. Delete the
same pointer twice. Then allocate pointers and check for duplicates or just
for crashes."
The writer is more than a detached academic. Not mentioned in the book is
the fact that Horstmann is author of a commercial word-processing package
for scientific documents called ChiWriter. This complex program has served
as proving ground for the author's design hints and coding tips.
Recently, I've encountered programmers who have already completed the slow
march up the learning curve of C++ and are ready to embark on a project
involving Microsoft Visual C++ (MSVC) and Microsoft Foundation Class (MFC),
only to find themselves at sea in a new ocean of information: the 80,000
lines of dense C++ code that comprise MFC, and the way this codebase interacts
with the underlying Windows API. Having been in the same boat, I empathize
strongly.
In contrast with the general topic of C++, there are very few independent
sources of information on MSVC and MFC. One possible explanation, again,
has to do with the complexity of the subject. Unless you work at Microsoft,
you probably have not had the opportunity to work extensively with the latest
compiler versions, given the rapid release rate of the languages division
there.
The bulk of published material on this topic originates from Microsoft --
the documentation, tutorials, tech notes and sample code packaged with its
compiler and also found on the Microsoft Developer Network CD-ROM (MSDN).
There is also the Microsoft Press book, Inside Visual C++, Second Edition,
by David Kruglinksi (covering MSVC 1.5 and MFC 2.5). Fortunately, all these
official works are of uniformly high quality and go a long way towards providing
the tribal knowledge -- the accumulated wisdom about tips, traps, and techniques
necessary for being productive in a complex environment. The Books Online
information packaged with MSVC, plus the additional information in the MSDN
CD, is essential for any developer working on the Windows platform, even
if you use another vendors compiler. Having the material in electronic form
facilitates browsing and searching, although it does hinder extended reading.
If you have a laser printer, however, it's easy enough to print out even
entire chapters for offline perusal.
But what happens if your programming problem is not mentioned in this material?
For example, I recently wanted to use the CPropertySheet class in MFC to
implement a tabbed dialog app in 16-bit Windows. This class is supported
in MSVC 2.1 for Windows 95 and Windows NT, but the 16-bit compiler (MSVC
1.5) isn't mentioned anywhere in the class reference docs. It turns out
that CPropertySheet works fine with V1.52 or later; you just use it in the
same manner as in V2.1. To find this out, I had to break my small-is-beautiful
rule and consult some wide and heavy books.
I was pleasantly surprised by the quality of the Kruglinski book and of
three other recent books on MSVC and MFC: Win32 Programming using Visual
C++, by Mike Blaszczak; Visual C++ How-To, by Scott Stanfield
et al.; and Visual C++ 2, by Marshall Brain and Lance Lovette. All
are safe choices and provide good hard-copy coverage of MSVC and MFC, although
none contain information that goes substantially beyond the product documentation.
The Kruglinski, Blaszczak, and Brain/Lovette books all follow the traditional
approach of covering the MSVC package on a component-by-component basis,
with a chapter on, say, AppWizard, another on dialogs, one on ODBC, and
so on.
The Visual C++ How-To is distinguished by its question-oriented problem-solving
approach. There is no overview or introductory material; instead, the book
presents a list of very specific questions, such as "How do I write
a customized DDX/DDV routine?" or "How do I display a progress
meter in the status bar?" Each question is answered in a half-dozen
or so pages, which contain step-by-step instructions for adding lines of
code to compiler-generated source files. (As you perhaps know, much of MFC
programming involves interacting with Class Wizard and related code generators.)
Because of this approach, Visual C++ How-To complements the other
three books -- think of it as additional Tech Notes that Microsoft did not
write.
If I had to pick only one of the other three, I'd choose Win32 Programming
using Visual C++. Perhaps because Blaszczak was part of the MFC development
team, his book seems to have that extra modicum of insight into the design
motives behind some MFC constructs. He does first restate the party line,
which is that you don't need to know how MFC (or any other app framework)
works in order to use it. But then he admits that when things go wrong,
everyone feels the need to understand the internals behind mechanisms such
as message maps or DDX/DDV tables. Although the book has a more conventional
purpose than delving under the hood of MFC, often you can read between the
lines of his narrative and get a sense of the underlying design goals. In
the case of message maps, he devotes ten full pages to unraveling the twisted
set of macros that implement this peculiar mechanism.
In summary, when you need the answer to a specific programming problem,
it's fairly easy to sacrifice principles of elegance and conciseness. The
Kruglinski, Blaszczak, and Brain/Lovette books contain plenty of answers
(the Brain/Lovette book comes with an online index, not just a listings
diskette). Any one of them would be a worthwhile addition to your library.
Ironically, my particular question turned out not be found in any of these
books, and I had to rely on the tribal knowledge of a friend to solve the
CPropertySheet problem.