Previous Table of Contents Next


At the time, I felt that there was a tradeoff between having separate interface and implementation declarations (as in Modula-2) plus a tool (linker) for matching them up and having a single class declaration, plus a tool (a dependency analyzer) that considered the interface part separately from the implementation details for the purposes of recompilation. It appears that I underestimated the complexity of the latter and also that the proponents of the former approach underestimate the cost (in terms of porting problems and runtime overheads) of the former.

The concern for simplistic implementations was partly a necessity caused by the lack of resources for developing C with Classes and partly a distrust of languages and mechanisms that required clever techniques. An early formulation of a design goal was that C with Classes “should be implementable without using an algorithm more complicated than a linear search.” Wherever that rule of thumb was violated—as in the case of function overloading (section 6.3.3.3)—it led to semantics that were more complicated than anyone felt comfortable with and typically also led to implementation complications.

The aim—based on my Simula experience—was to design a language that would be easy enough to understand to attract users and easy enough to implement to attract implementers. For C with Classes, and later C++, to survive in competition with C, a relatively simple implementation used by a relatively novice user in a relatively unsupportive programming environment would have to deliver code that compared favorably with C code in development time, correctness, runtime speed, and code size.

This was part of a philosophy of fostering self-sufficiency among users. The aim was always—and explicitly—to develop local expertise in all aspects of using C++. Most programming language and tools purveyors must follow the exact opposite strategy. They keep users dependent on services that generate revenue for a central support organization and consultants. In my opinion, this contrast is a deep reason for some of the differences between C++ and many other languages.

The decision to work in the relatively primitive—and almost universally available—framework of the C linking facilities caused the fundamental problem that a C++ compiler must always work with only partial information about a program. An assumption made about a program could possibly be violated by a program written tomorrow in some other language (such as C, Fortran, or assembler) and linked in—possibly after the program has started executing. This problem surfaces in many contexts. It is hard for an implementation to guarantee

  That something is unique
  That (type) information is consistent
  That something is initialized

In addition, C provides only the feeblest support for the notion of separate namespaces so that avoiding namespace pollution by separately written program segments becomes a problem (see section 6.5.7). Over the years, C++ has tried to face all these challenges without departing from the fundamental model and technology that give portability, but in the C with Classes days, we simply relied on the C technique of header files.

Through the acceptance of the C linker came another principle for the development of C++: that C++ is just one language in a system and not a complete system. In other words, C++ accepts the role of a traditional programming language with a fundamental distinction between the language, the operating system, and other important parts of the programmer’s world. This delimits the role of the language in a way that is hard to do for a language, such as Smalltalk or Lisp, that is conceived as a complete system or environment. It makes it essential that a C++ program fragment can call program fragments written in other languages and that a C++ program fragment can itself be called by program fragments written in other languages. Being “just a language” also allows C++ implementations to benefit directly from tools written for other languages.

The need for a programming language and the code written in it to be just a cog in a much larger machine is of utmost importance to most industrial users, yet such coexistence with other languages and systems was apparently not a major concern to most theoreticians, would-be perfectionists, and academic users. I believe this to be one of the main reasons for C++’s success.


Previous Table of Contents Next