Like any human language, C++
provides a way to express concepts. If successful, this medium of expression
will be significantly easier and more flexible than the alternatives as problems
grow larger and more complex.
You can’t just look at C++ as a
collection of features; some of the features make no sense in isolation. You can
only use the sum of the parts if you are thinking about design, not
simply coding. And to understand C++ this way, you must understand the problems
with C and with programming in general. This book discusses programming
problems, why they are problems, and the approach C++ has taken to solve such
problems. Thus, the set of features I explain in each chapter will be based on
the way that I see a particular type of problem being solved with the language.
In this way I hope to move you, a little at a time, from understanding C to the
point where the C++ mindset becomes your native tongue.
Throughout, I’ll be taking the
attitude that you want to build a model in your head that allows you to
understand the language all the way down to the bare metal; if you encounter a
puzzle, you’ll be able to feed it to your model and deduce the answer. I
will try to convey to you the insights that have rearranged my brain to make me
start “thinking in
C++.”
This book is a thorough rewrite of the
first edition to reflect all of the changes introduced in C++ by the
finalization of the C++ Standard, and also to reflect what I’ve learned
since writing the first edition. The entire text present in the first edition
has been examined and rewritten, sometimes removing old examples, often changing
existing examples and adding new ones, and adding many new exercises.
Significant rearrangement and re-ordering of the material took place to reflect
the availability of better tools and my improved understanding of how people
learn C++. A new chapter was added which is a rapid introduction to the
C concepts and basic C++ features for those who don’t
have the C background to tackle the rest of the book. The
CD ROM bound into the back of the book contains a seminar
that is an even gentler introduction to the C concepts necessary to understand
C++ (or Java). It was created by Chuck Allison for my
company (MindView, Inc.), and it’s called
“Thinking in C: Foundations for Java and C++.”
It introduces you to the aspects of C that are necessary for you to move on to
C++ or Java, leaving out the nasty bits that C programmers must deal with on a
day-to-day basis but that the C++ and Java languages steer
you away from (or even eliminate, in the case of Java).
So the short answer to the question
“what’s different in the 2nd edition?” is: what
isn’t brand new has been rewritten, sometimes to the point where you
wouldn’t recognize the original examples and
material.
I clawed my way into C++ from exactly the
same position I expect many of the readers of this book are in: as a programmer
with a very no-nonsense, nuts-and-bolts attitude about programming. Worse, my
background and experience was in hardware-level embedded programming, in which C
has often been considered a high-level language and an inefficient overkill for
pushing bits around. I discovered later that I wasn’t even a very good C
programmer, hiding my ignorance of structures, malloc( ) and
free( ), setjmp( ) and longjmp( ), and other
“sophisticated” concepts, scuttling away in shame when the subjects
came up in conversation instead of reaching out for new
knowledge.
When I began my struggle to understand
C++, the only decent book was Bjarne Stroustrup’s
self-professed “expert’s
guide,[1]”
so I was left to simplify the basic concepts on my own. This resulted in my
first C++ book,[2]
which was essentially a brain dump of my experience. That was designed as a
reader’s guide to bring programmers into C and C++ at the same time. Both
editions[3] of the
book garnered enthusiastic response.
At about the same time that Using
C++ came out, I began teaching the language in seminars and presentations.
Teaching C++ (and later, Java) became my profession; I’ve seen nodding
heads, blank faces, and puzzled expressions in audiences all over the world
since 1989. As I began giving in-house training to smaller groups of people, I
discovered something during the exercises. Even those people who were smiling
and nodding were confused about many issues. I found out, by creating and
chairing the C++ and Java tracks at the Software Development Conference for many
years, that I and other speakers tended to give the typical audience too many
topics, too fast. So eventually, through both variety in the audience level and
the way that I presented the material, I would end up losing some portion of the
audience. Maybe it’s asking too much, but because I am one of those people
resistant to traditional lecturing (and for most people, I believe, such
resistance results from boredom), I wanted to try to keep everyone up to
speed.
For a time, I was creating a number of
different presentations in fairly short order. Thus, I ended up learning by
experiment and iteration (a technique that also works well in C++ program
design). Eventually I developed a course using everything I had learned from my
teaching experience. It tackles the learning problem in discrete, easy-to-digest
steps and for a hands-on seminar (the ideal learning situation) there are
exercises following each of the presentations. You can find out about my
public seminars at
www.BruceEckel.com, and you can also learn about the seminars that
I’ve turned into CD ROMs.
The first edition of this book developed
over the course of two years, and the material in this book has been road-tested
in many forms in many different seminars. The feedback that I’ve gotten
from each seminar has helped me change and refocus the material until I feel it
works well as a teaching medium. But it isn’t just a seminar handout; I
tried to pack as much information as I could within these pages, and structure
it to draw you through onto the next subject. More than anything, the book is
designed to serve the solitary reader who is struggling with a new programming
language.
My goals in this book are
to:
C++ is a language in which new and
different features are built on top of an existing syntax. (Because of this, it
is referred to as a
hybrid
object-oriented programming language.) As more people pass through the learning
curve, we’ve begun to get a feel for the way programmers move through the
stages of the C++ language features. Because it appears to be the natural
progression of the procedurally-trained mind, I decided to understand and follow
this same path and accelerate the process by posing and answering the questions
that came to me as I learned the language and those questions that came from
audiences as I taught the language.
This course was designed with one thing
in mind: to streamline the process of learning C++. Audience feedback helped me
understand which parts were difficult and needed extra illumination. In the
areas in which I got ambitious and included too many features all at once, I
came to know – through the process of presenting the material – that
if you include a lot of new features, you have to explain them all, and the
student’s confusion is easily compounded. As a result, I’ve taken a
great deal of trouble to introduce the features as few at a time as possible;
ideally, only one major concept at a time per chapter.
The goal, then, is for each chapter to
teach a single concept, or a small group of associated concepts, in such a way
that no additional features are relied upon. That way you can digest each piece
in the context of your current knowledge before moving on. To accomplish this, I
leave some C features in place for longer than I would prefer. The benefit is
that you will not be confused by seeing all the C++ features used before they
are explained, so your introduction to the language will be gentle and will
mirror the way you will assimilate the features if left to your own
devices.
Here is a brief description of the
chapters contained in this book:
Chapter 1: Introduction to
Objects. When projects became too big and complicated to easily maintain,
the “software crisis”
was born, with programmers saying, “We can’t get projects done, and
if we can, they’re too expensive!” This precipitated a number of
responses, which are discussed in this chapter along with the ideas of
object-oriented programming (OOP) and how it attempts to solve the software
crisis. The chapter walks you through the basic concepts and features of OOP and
also introduces the analysis and design process. In addition, you’ll learn
about the benefits and concerns of adopting the language and suggestions for
moving into the world of C++.
Chapter 2: Making and Using
Objects. This chapter explains the process of building programs using
compilers and libraries. It introduces the first C++ program in the book and
shows how programs are constructed and compiled. Then some of the basic
libraries of objects available in Standard C++ are introduced. By the time you
finish this chapter you’ll have a good grasp of what it means to write a
C++ program using off-the-shelf object libraries.
Chapter 3: The C in C++. This
chapter is a dense overview of the features in C that are used in C++, as well
as a number of basic features that are available only in C++. It also introduces
the “make” utility that’s common in the software development
world and that is used to build all the examples in this book (the source code
for the book, which is available at www.BruceEckel.com, contains
makefiles for each chapter). Chapter 3 assumes that you have a solid grounding
in some procedural programming language like Pascal, C, or even some flavors of
Basic (as long as you’ve written plenty of code in that language,
especially functions). If you find this chapter a bit too much, you should first
go through the Thinking in C seminar on the CD that’s bound with
this book (and also available at www.BruceEckel.com).
Chapter 4: Data Abstraction. Most
features in C++ revolve around the ability to create new data types. Not only
does this provide superior code organization, but it lays the groundwork for
more powerful OOP abilities. You’ll see how this idea is facilitated by
the simple act of putting functions inside structures, the details of how to do
it, and what kind of code it creates. You’ll also learn the best way to
organize your code into header files and implementation files.
Chapter 5: Hiding the
Implementation. You can decide that some of the data and functions in
your structure are unavailable to the user of the new type by making them
private. This means that you can separate the underlying implementation
from the interface that the client programmer sees, and thus allow that
implementation to be easily changed without affecting client code. The keyword
class is also introduced as a fancier way to describe a new data type,
and the meaning of the word “object” is demystified (it’s a
fancy variable).
Chapter 6: Initialization and
Cleanup. One of the most common C errors results from uninitialized
variables. The constructor in C++ allows you to guarantee that variables
of your new data type (“objects of your class”) will always be
initialized properly. If your objects also require some sort of cleanup, you can
guarantee that this cleanup will always happen with the C++
destructor.
Chapter 7: Function Overloading and
Default Arguments. C++ is intended to help you build big, complex
projects. While doing this, you may bring in multiple libraries that use the
same function name, and you may also choose to use the same name with different
meanings within a single library. C++ makes this easy with function
overloading, which allows you to reuse the same function name as long as the
argument lists are different. Default arguments allow you to call the same
function in different ways by automatically providing default values for some of
your arguments.
Chapter 8: Constants. This
chapter covers the const and volatile keywords, which have
additional meaning in C++, especially inside classes. You’ll learn what it
means to apply const to a pointer definition. The chapter also shows how
the meaning of const varies when used inside and outside of classes and
how to create compile-time constants inside classes.
Chapter 9: Inline Functions.
Preprocessor macros eliminate function call overhead, but the preprocessor also
eliminates valuable C++ type checking. The inline function gives you all the
benefits of a preprocessor macro plus all of the benefits of a real function
call. This chapter thoroughly explores the implementation and use of inline
functions.
Chapter 10: Name Control.
Creating names is a fundamental activity in programming, and when a project
gets large, the number of names can be overwhelming. C++ allows you a great deal
of control over names in terms of their creation, visibility, placement of
storage, and linkage. This chapter shows how names are controlled in C++ using
two techniques. First, the static keyword is used to control visibility
and linkage, and its special meaning with classes is explored. A far more useful
technique for controlling names at the global scope is C++’s
namespace feature, which allows you to break up the global name space
into distinct regions.
Chapter 11: References and the
Copy-Constructor. C++ pointers work like C pointers with the additional
benefit of stronger C++ type checking. C++ also provides an additional way to
handle addresses: from Algol and Pascal, C++ lifts the reference, which
lets the compiler handle the address manipulation while you use ordinary
notation. You’ll also meet the copy-constructor, which controls the way
objects are passed into and out of functions by value. Finally, the C++
pointer-to-member is illuminated.
Chapter 12: Operator Overloading.
This feature is sometimes called “syntactic sugar;” it lets you
sweeten the syntax for using your type by allowing operators as well as function
calls. In this chapter you’ll learn that operator overloading is just a
different type of function call and you’ll learn how to write your own,
dealing with the sometimes-confusing uses of arguments, return types, and the
decision of whether to make an operator a member or friend.
Chapter 13: Dynamic Object
Creation. How many planes will an air-traffic system need to manage? How
many shapes will a CAD system require? In the general programming problem, you
can’t know the quantity, lifetime, or type of objects needed by your
running program. In this chapter, you’ll learn how C++’s new
and delete elegantly solve this problem by safely creating objects on the
heap. You’ll also see how new and delete can be overloaded
in a variety of ways so you can control how storage is allocated and
released.
Chapter 14: Inheritance and
Composition. Data abstraction allows you to create new types from scratch,
but with composition and inheritance, you can create new types from existing
types. With composition, you assemble a new type using other types as pieces,
and with inheritance, you create a more specific version of an existing type. In
this chapter you’ll learn the syntax, how to redefine functions, and the
importance of construction and destruction for inheritance and
composition.
Chapter 15: Polymorphism and virtual
Functions. On your own, you might take nine months to discover and
understand this cornerstone of OOP. Through small, simple examples, you’ll
see how to create a family of types with inheritance and manipulate objects in
that family through their common base class. The virtual keyword allows
you to treat all objects in this family generically, which means that the bulk
of your code doesn’t rely on specific type information. This makes your
programs extensible, so building programs and code maintenance is easier and
cheaper.
Chapter 16: Introduction to
Templates. Inheritance and composition allow you to reuse object
code, but that doesn’t solve all of your reuse needs. Templates allow you
to reuse source code by providing the compiler with a way to substitute
type names in the body of a class or function. This supports the use of
container class libraries, which are important tools for the rapid,
robust development of object-oriented programs (the Standard C++ Library
includes a significant library of container classes). This chapter gives you a
thorough grounding in this essential subject.
Additional topics (and more advanced
subjects) are available in Volume 2 of this book, which can be downloaded from
the Web site
www.BruceEckel.com.
Throughout this book, when referring to
conformance to the ISO C standard, I will generally just say
‘C.’ Only if it is
necessary to distinguish between Standard C and older, pre-Standard versions of
C will I make a distinction.
At this writing the
C++ Standards
Committee was finished working on the language. Thus, I will use the term
Standard C++
to refer to the standardized language. If I simply refer
to C++ you should assume I mean “Standard C++.”
There is some confusion over the actual
name of the C++ Standards Committee and the name of the standard itself. Steve
Clamage, the committee chair, clarified this:
There are two C++ standardization
committees: The NCITS (formerly X3) J16 committee and the ISO JTC1/SC22/WG14
committee. ANSI charters NCITS to create technical committees for developing
American national standards.
J16 was chartered in 1989 to create an
American standard for C++. In about 1991 WG14 was chartered to create an
international standard. The J16 project was converted to a "Type I"
(International) project and subordinated to the ISO standardization effort.
The two committees meet at the same
time at the same location, and the J16 vote constitutes the American vote on
WG14. WG14 delegates technical work to J16. WG14 votes on the technical work of
J16.
The C++ standard was originally
created as an ISO standard. ANSI later voted (as recommended by J16) to adopt
the ISO C++ standard as the American standard for C++.
Your compiler may
not support all of the features discussed in this book, especially if you
don’t have the newest version of the compiler. Implementing a language
like C++ is a Herculean task, and you can expect that the features will appear
in pieces rather than all at once. But if you attempt one of the examples in the
book and get a lot of errors from the compiler, it’s not necessarily a bug
in the code or the compiler; it may simply not be implemented in your particular
compiler
yet.
[1]
Bjarne Stroustrup, The C++ Programming Language, Addison-Wesley, 1986
(first edition).
[2]
Using C++, Osborne/McGraw-Hill 1989.
[3]
Using C++ and C++ Inside & Out, Osborne/McGraw-Hill
1993.