How To Teach C++ Badly
I've been teaching C++ a long time, so I've learned from a lot of mistakes along the way. As a result, I'm not surprised to see other people make similar mistakes. What does surprise me, however, is to see people make mistakes that there is no longer any need to make, because the language has changed since I first made them, and now offers alternative ways of solving the problems that led to the mistakes in the first place.
Here are a few of the most common teaching mistakes. If you want to learn how to confuse beginning C++ programmers, these suggestions are a fine place to start.
Use arrays. Because the size of an array is part of its type, the number of elements in a C++ array must be known during compilation. This requirement means that most C++ programs that use arrays will have restrictions built into them that will cause trouble for their programmers as their programs grow. Today there is rarely any reason to use arrays; the vector template from the standard library can usually substitute for an array without the restrictions.
Use new and delete for dynamic arrays. Once upon a time, new and delete were the obvious alternatives to using fixed-sized arrays. However, they have three significant disadvantages over the library vector template: (1) You have to remember to execute a delete for every new. (2) There is no easy way to change the size of a region of memory allocated by new. (3) Because of (1), it is hard to write exception-safe code that uses new and delete. Before the vector template came along, new and delete were plausible alternatives to fixed-size arrays -- but no longer.
Teach constructors and destructors at the same time. Constructors and destructors seem at first to go together, so it seems logical to teach them together. However, when a class uses a destructor, each object of that class is effectively controlling a resource that the destructor frees when the object goes away. Copying an object is one way of creating an object, so when you copy an object that allocates a resource, you have to do something about that resource. Otherwise, when you destroy the original object and the copy, you run the risk of trying to freeing the same resource twice.
This observation, of course, leads to the Rule of Three: Briefly, whenever a class has a destructor, it almost always also needs a copy constructor and a copy-assignment operator. However, these two members are much harder for beginners to understand than are other kinds of constructors. Therefore, I believe it is a good idea to defer talking about destructors until the reader is ready to understand copy constructors and copy-assignment operators.
Once upon a time, it was difficult to put off talking about destructors. However, you do not need to write a destructor in a class with data members that manage their own resources. Therefore, so long as you use library facilities such as vector, and smart pointers such as the shared_ptr template in the forthcoming C++ standard, there is no reason not to put off talking about destructors.
Use bubble sort. Bubble sort is a quadratic algorithm. There is simply no reason to explain quadratic algorithms to beginners except perhaps as cautionary examples of programming techniques to avoid. Moreover, beginners seem to have a hard time figuring out how sort algorithms work in the first place. With the standard-library sort algorithms, there is every reason to encourage beginners to learn how to use sorted sequences, and why they are useful, before turning them loose to write their own sort algorithms.
Define operator+ and similar operators as member functions rather than friends. When you have an operator or other function that treats two or more arguments interchangeably, it should never be a member function. It is just too confusing for a+b to work and b+a to fail. If you have a methodology that requires such functions to be members, then you should revise your methodology.
Use printf. I am amazed that people still do this -- but sometimes they do. Because printf is a C function, it is limited to the data structures defined in C. In particular, you cannot use printf to print a C++ standard-library string -- so if you intend to use printf, you probably have to use character arrays in place of strings. This observation brings us back to my original remarks about arrays.
Not only do these suggestions describe common ways to teach C++ badly, they also describe common ways of writing bad C++ textbooks. As a result, one way of evaluating a C++ textbook quickly is to see how many of these teaching techniques the book uses. It is usually easy to tell. For example, a quick glance at the table of contents will tell you when the book first talks about arrays and when it first talks about vectors. If, as often happens, the book talks about arrays in the first few dozen pages, but does not mention vectors until two-thirds of the way through, you can safely put that book back on the shelf without another look.
I intend to talk in more detail about these teaching techniques, and what I think are better alternatives to them, in coming posts.