Previous Table of Contents Next


6.8.2.1. What Should and Could Have Been Different?

Given a clean slate, what would be a better language than C++ for the things C++ is meant for? Consider the first-order decisions: use of static type checking, clean separation between language and environment, no direct support for concurrency, ability to match the layout of objects and call sequences for languages such as C and Fortran, and C compatibility.

First, I considered, and still consider, static type checking essential both as a support for good design and secondarily for delivering acceptable runtime efficiency. Were I to design a new language for what C++ is used for today, I would again follow the Simula model of type checking and inheritance, not the Smalltalk or Lisp models. As I have said many times, “Had I wanted an imitation Smalltalk, I would have built a much better imitation. Smalltalk is the best Smalltalk around. If you want Smalltalk, use it” (Stroustrup, 1990). Having both static type checking and dynamic type identification (for example, in the form of virtual function calls) implies some difficult tradeoffs compared to languages with only static or only dynamic type checking. The static type model and the dynamic type model cannot be identical and thus there will be some complexity and inelegance that can be avoided by supporting only one type model. However, I wouldn’t want to write programs with only one model.

I also still consider a separation between the environment and the language essential. I do not want to use only one language, only one set of tools, and only one operating system. To offer a choice, separation is necessary. However, once the separation exists, one can provide different environments to suit different tastes and different requirements for supportiveness, resource consumption, and portability.

We never have a clean slate. Whatever new things we do, we must also make it possible for people to make a transition from old tools and ideas to new. Thus, if C hadn’t been there for C++ to be almost compatible with, then I would have chosen to be almost compatible with some other language.

Should a new language support garbage collection directly, say, as Modula-3, Smalltalk, and Java do? If so, could C++ have met its goals had it provided garbage collection? Garbage collection is great when you can afford it. Therefore, the option of having garbage collection is clearly desirable. However, garbage collection can be costly in terms of runtime, real-time response, and porting effort (exactly how costly is the topic of much confused debate). Therefore, being forced to pay for garbage collection at all times isn’t necessarily a blessing. C++ allows optional garbage collection (Ellis & Stroustrup, 1990), and I expect to see many experiments with garbage-collecting C++ implementations in the near future. However, I am convinced (after reviewing the issue many times over the years) that had C++ depended on garbage collection, it would have been stillborn. By the mid-1990s, very effective garbage collectors were available for C++. Thus, garbage-collected C++ is an option for both experimental and production systems.

Should a language have reference semantics for variables (that is, a name is really a pointer to an object allocated elsewhere) like Smalltalk, Java, or Clu or true local variables like C and Pascal? This question relates to several issues such as coexistence with other languages, compatibility, and garbage collection. Simula and Java dodged the question by having references to class objects (only) and true variables for objects of built-in types (only). Again, I consider it an open issue whether a language could be designed that provided the benefits of both references and true local variables without ugliness. Given a choice between elegance and the benefits of having both references and true local variables, I’ll take the references plus true local variables.

6.8.2.2. What Should Have Been Left Out?

Even Classes: An Abstract Data Type Facility for the C Language (Stroustrup, 1980a) voiced concern that C with Classes might have become too large. I think a smaller language is number one on any wish list for C++, yet people deluge me and the standards committee with extension proposals. The fundamental reason for the size of C++ is that it supports more than one way of writing programs, more than one programming paradigm. From one point of view, C++ is really four languages in one: a C-like language plus an Ada-like language, plus a Simula-like language, plus a language for generic programming, plus what it takes to integrate those features into a coherent whole.

Brian Kernighan observed that in C, there is usually about one way of solving a given problem, whereas in C++, there are more ways. I conjecture that there typically is more than one way in C but that people don’t see them. In C++, there are typically at least three alternatives and experienced people have quite a hard time not seeing them. There always is a design choice, but in most languages the language designer has made the choice for you. For C++ I did not; the choice is yours. This is naturally abhorrent to people who believe that there is exactly one right way of doing things. It can also scare beginners and teachers who feel that a good language is one that you can completely understand in a week. C++ is not such a language. It was designed to provide a tool set for a professional, and complaining that there are too many features is like the layman looking into an upholsterer’s tool chest and exclaiming that there couldn’t possibly be a need for all those little hammers.

People sometimes point to C compatibility, overloading, and multiple inheritance as features that C++ would have been better without. My estimate is that C compatibility was and remains essential, that overloading is critical for many techniques (especially in libraries) so that C++ wouldn’t have succeeded without it, and that multiple inheritance was useful and has steadily increased in importance over the years as people more directly model their ideas using inheritance.


Previous Table of Contents Next