Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Learning & Teaching C++ Programming


February, 2005: Learning & Teaching C++Programming

Andrew Koenig is a former AT&T researcher and programmer. He is author of C Traps and Pitfalls and, with Barbara, coauthor of Ruminations on C++ and Accelerated C++. Barbara Moo is an independent consultant with 20 years of experience in the software field.


We expect that the fourth edition of the classic C++ Primer will be available soon after you read this. In this new edition, Barbara Moo joins Stanley Lippman and Josée Lajoie, authors of the third edition. While you likely will see advertising promoting the new C++ Primer, that's not our intent here.

Readers of this column know that we have been thinking for a long time about how best to teach C++, and that we wrote Accelerated C++ as a consequence of these thoughts. To that end, we limited Accelerated C++'s coverage to only material we think every C++ programmer certainly needs to know, while C++ Primer covers material that C++ programmers might need to know. This difference in coverage leads logically to a substantial difference in organization that's determined by how we teach and learn C++ programming. And that's the focus of this column.

Modern Abstractions and Examples

When we set out to write Accelerated C++, we wanted it to be radically, relentlessly modern. We started by pretending that C did not exist, blithely ignoring 25 years of history. As we wrote the book, we kept asking the same question: Of all the ideas we might introduce at each point, which one would readers find most useful? Each time we answered this question, we found a programming example that introduced that idea, along with a way to connect the example to the ones that came before it. When we were done, we had a book that covered the most useful ideas in C++ in context, showing not only why each idea was useful but also how to use it.

What makes an idea useful is what you can do with it. Accordingly, our emphasis on utility led us to present powerful, high-level, abstract ideas ahead of the lower-level ideas that support them. In particular, we believed that by the time Accelerated C++ was published, the C++ Standard Library would be widely enough available that we could rely on its facilities, such as the vector and string classes, in place of lower-level facilities, such as arrays and C-style strings.

This reliance was a break with past practice. The third edition of the C++ Primer came out in 1998, about the same time as the C++ Standard. However, implementations—especially implementations of the Standard Library—had not yet advanced to where programmers could confidently trust them. Accordingly, it would have been unwise for the C++ Primer to recommend such notions as using vectors instead of arrays. Indeed, even for the first couple of years after Accelerated C++ was published in 2000, we still had to answer questions from readers whose compilers couldn't handle the book's example programs.

This situation has completely changed. Today's C++ implementations are good enough that we no longer see any excuse for avoiding the Standard Library. Accordingly, the biggest change between the third and fourth editions of the C++ Primer is that the fourth edition places much less emphasis on the "C" parts of C++ and much more emphasis on the "++" parts. Like Accelerated C++, and unlike the third edition, the new C++ Primer teaches the standard vector and string classes early, and covers arrays and C-style strings only to the extent that programmers really need to know about them. Moreover, like Accelerated C++ and unlike the third edition, the new C++ Primer shows how to use notions such as constructors and generic functions before showing how to define them.

We deprecated arrays for a good reason. The trouble with arrays is that you must specify an array's size when you create it. Accordingly, a program that wants to create an array's elements one at a time—say, by reading them from a file—has to invent an initial size without knowing how many elements the array will eventually have. Moreover, if the array needs to grow beyond its initial, invented size, the program must arrange to reallocate the array.

If you're accustomed to using vectors, it's easy to write:

vector<int> v;
int n;
while (cin >> n)
   v.push_back(n);

and not have to worry about how many elements v might eventually hold. However, you have to think to do so in the first place. If you're not in the habit of using vectors, and instead your only impulse is to use built-in arrays, even such a simple piece of code as this one is a nuisance to write. If you're skeptical, try it yourself and see.

In addition to preferring high-level abstractions over their lower-level counterparts, we let another principle govern our choice of topics: Show how to use abstractions before explaining how they work. Modern C++ includes many abstractions, from core-language ideas such as constructors, destructors, and inheritance to library facilities such as containers and algorithms. Most C++ books explain how these abstractions work before explaining how to use them. For example, it is typical to explain how to define a class or a generic function before describing how to use one. After all, how can readers use something without first having one available to use?

The Standard Library let us reverse that order: Before showing how to define a class or write a generic function, we were able to use classes and generic functions from the Standard Library. Accordingly, we could defer showing how to define new abstractions until after showing readers what such abstractions can do and why they are useful.

These principles—favoring high-level ideas, presenting ideas in context, and using abstractions before building them—pervade Accelerated C++ and define much of its structure. We could have gone beyond what we covered in Accelerated C++ if we were willing to relax our insistence on presenting ideas only in context. We could have presented the material in a more conventional order if we had been willing to explain abstractions before using them. However, our teaching experience convinced us that our strategy worked so well that we wanted to be consistent about using it. There were already plenty of other books that were organized more conventionally.

We are happy that many readers have found our approach useful. We are also happy that Stan asked Barbara to work on revising the C++ Primer, both because it showed that he appreciated our approach and because the revision was another opportunity to take advantage of the now widespread availability of the Standard Library.

Two Kinds of Basics

In our previous column ("What Does 'Advanced C++' Mean?", December 2004), we suggested reserving the term "advanced" to refer to what you learn after mastering the basics. This suggestion naturally leads to another question: What are the basics?

We can think of two plausible answers:

  • What every C++ programmer needs to know to write useful programs.
  • What C++ programmers might potentially need to know to handle a wide range of applications.

To see that these answers are different, you need look no further than the goto statement.

Many programmers today advocate never using goto statements for any reason, and indeed well-known programming languages such as Java and Python do not even have a goto statement. Accordingly, it is reasonable to omit goto from the concepts to be learned to write useful programs.

On the other hand, although programmers shouldn't be writing goto statements directly, they may encounter goto statements in programs written by others. Moreover, people sometimes write programs that generate other programs. It can be useful for such generated programs to contain goto statements. Therefore, there may be reasons to learn what a goto statement does, even if you never write one yourself.

As another example, consider placement new and delete. It is possible to program for an entire career without needing either of these concepts. However, in some applications, there is no substitute. A book that covers only what everyone needs to know will omit placement new and delete; a book that extends to what people might need to know will include them.

Two Teaching Strategies

Not only do we see two plausible answers to the question, "What are the basics?" but we also see two plausible teaching strategies. One strategy is to group similar facilities together. For example, arrays and vectors are both kinds of containers, so it makes sense to describe them together. Similarly, a pointer is a kind of iterator, so it makes sense to describe pointers and iterators together—especially if arrays are already grouped with vectors.

Another (quite different) strategy is to describe language facilities only in the context of solving particular problems. Most people learn more quickly if they can immediately use what they learn. A book that follows this strategy presents its major concepts in a surprisingly unconventional order.

For instance, to describe how to use arrays, our strategy says that we must find an example that needs to use arrays. However, when an array works, a vector usually works better. What example can we find for which arrays are obviously better than vectors?

The most telling example is implementing vectors. After all, if you set out to implement a vector class, it wouldn't be fair to assume that such a class already exists. However, if we are to use this example, it implies that we cannot discuss arrays until we have covered classes in enough detail to make it possible to implement vectors in the first place. In other words, the desire to describe language facilities in context leads to the surprising notion that we should resist talking about arrays until we are confident that our readers have learned enough to be ready to use them to implement vectors.

If, on the other hand, we are willing to use abstract examples to illustrate language facilities, then it is easier and more logical to describe arrays soon after describing vectors. Doing so will make it easier to explain the similarities and differences between the two data structures.

Four Different Curricula?

We have seen that there are two fundamental decisions to make about how to cover the basics of C++:

  • Do "the basics" include information that some programmers but not others might need, or should they be limited to universally useful ideas?
  • Should the material be organized around language and library facilities or around examples and programming techniques?

Two independent questions yield four possibilities. However, a closer look shows that the questions are not as independent as they appear.

Let's begin by considering the case where we wish to include material that is useful to some readers but not all. In this case, it is challenging to come up with programming examples that are plausible and easy to understand. How can we find universally interesting examples of specialized programming techniques? Accordingly, we believe that in this case, the second answer probably has to be that the material should be organized around language and library facilities.

Now let's assume that we wish to cover only material that everyone needs to know. In that case, we think that it is better to organize the ideas around how to use them than it is to group ideas that are superficially similar. So, for example, instead of describing all types together, we would rather introduce each type in the context of a realistic example that explains why that type is useful and how to use it. After all, if every idea we cover is generally useful for writing programs, we should be able to find a useful program to illustrate each idea. And our experience is that whenever we can illustrate ideas with useful examples, people understand those ideas much more quickly.

In other words, the questions aren't really independent after all. Rather, we think there are really two plausible teaching strategies:

  • Use examples and programming problems to explain as much as possible. This strategy will result in covering the facilities needed to solve the programming problems that we use. Careful choice of problems will present a range of facilities that will serve most purposes. However, facilities such as goto statements and placement new and delete will escape coverage.
  • Group related facilities together and cover them systematically, using realistic examples to illustrate the facilities where possible and abstract examples otherwise. This strategy is more traditional, and has no limits on what it can cover. However, if it does present more material, it will have to take more time to do so.

Accelerated C++ embodies the first of these two approaches; the revised C++ Primer embodies the second. Many of the differences between these books come directly from these fundamentally different goals.

For example, the C++ Primer discusses vectors and arrays in Chapters 3 and 4, respectively. Accelerated C++ also discusses vectors in Chapter 3. However, it doesn't mention arrays until Chapter 10, more than half way through the book. As another example, the C++ Primer discusses the goto statement along with the other flow-of-control statements. In contrast, Accelerated C++ relegates it to a single paragraph in an appendix.

The Bottom Line

Unlike some books that teach C++, Accelerated C++ is organized around programming techniques, not language or library features. In contrast, the new C++ Primer retains its predecessor's overall organization, while expanding and integrating its coverage of the Standard Library. For example, it devotes one chapter to statements, another to expressions, and so on.

As another example, when we were writing Accelerated C++, we concentrated on features that we could connect to the ongoing examples in the book, and took a great deal of trouble to structure the examples so that they would encompass as many of the features as possible that we wanted to cover. In the analogous situation, the new C++ Primer is freer about constructing an example to describe the feature, even if that example is not connected to the rest of the book.

The new C++ Primer has more than twice as many pages as Accelerated C++. One reason for this size difference is that the C++ Primer covers more features than does Accelerated C++. Another is that except for its appendices, Accelerated C++ is not intended to be used as a reference manual; its goal is to teach its readers how to write useful C++ programs as quickly as possible.

The point is that there are different approaches to teaching and learning C++. We believe that approaching each of C++'s major ideas from two (or more) different vantage points helps you grasp ideas more deeply than if you had considered one viewpoint alone.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.