Notes for Bjarne Stroustrup The Design and Evolution of C++
Key concepts: C with Classes, Cfront, class, multi-paradigm, standard, static type checking.
Related theorists: Al Aho, Grady Booch, Steve Johnson, Dennis Ritchie, Takhteyev, Tanaka-Ishii.
Purports to be philosophical in sense of explaining design and evolution of C++, immediately dispelling notion of technological determinism by appealing to social context and iterative development.
(iii) Traditional books about programming and programming languages explain what a language is and how to use it. However, many people are also curious about why a language is the way it is and how it came to be that way. . . . It explains how C++ evolved from its first design to the language in use today. It describes the key problems, design aims, language ideas, and constraints that shaped C++, and how they changed over time.
Notes to the Reader
Add affordances of Simula to C for systems programming intention.
Flexibility of systems programming can relate to critique by Malabou based on Boltanski and Chiapello, relating C to the small people in any of seven cities of justification; like adding the sophisticated continental to American pragmatist Peirce, Simula equips the language with capabilities that can be leveraged by its practical users, which writing in the times, were building the early GNU/Linux Internet that nonetheless became part of the awful siren servers asymmetricaly profiting from joint user and system usage.
(1) C++ was designed to provide Simula's facilities for program organization together with C's efficiency and flexibility for systems programming. It was intended to deliver that to real projects within half a year of the idea. It succeeded.
Focus on key events, ideas, trends actually influencing the language, avoid revisionist history, mention people who contributed; contrast to decontextualized factual presentation of, not sure if it was the ENIAC, by Burks, Goldstein, and von Neumann that strays little from matters at hand of getting electronic computing going, long before any detailed programming languages were considered.
(1) It is not my aim to document every
little event, but to focus on the key events, ideas, and trends that
actually influenced the definition of C++ or might influence its
further evolution and use.
(2) Basically, I abhor revisionist history and try to avoid it.
(2) I try to mention people who contributed to the design and evolution of C++, and I try to be specific about their contribution and about when it occurred.
Attempts to judge bias of other works.
(2) In addition, the History of Programming Languages (HOPL-2) paper [Stroustrup,1993] that contains the central historical facts from this book was extensively reviewed and deemed free of unsuitable bias.
How to Read this Book
Interesting chart of language genealogy that begins where Knuth and Pardo conclude.
(6) The chart is not intended to be anywhere near complete except for significant influences on C++.
Unsettled philosophical question what is a programming language.
Good set of definitions of a general purpose programming language; compare to portrayals .
(7) One conclusion I drew from the wildly divergent comments on the HOPL-2 paper – and from many other sources – is that there is no guarantee on what a programming language really is and what its main purpose is supposed to be. Is a programming language a tool for instructing machines? A means of communicating between programmers? A vehicle for expressing higher-level designs? A notation for algorithms? A way of expressing relationships between concepts? A tool for experimentation? A means of controlling computerized devices? My view is that a general purpose programming language must be all of those to serve its diverse set of users.
Tanaka-Ishii set the lead in considering natural languages in light of studying programming languages.
Languages are grown, evolve.
(7) To serve its users, a general purpose programming language must be eclectic and take many practical and sociological factors into account. . . . It is my firm belief that all successful languages are grown and not merely designed from first principles. Principles underlie the first design and guide the further evolution of the language. However, even principles evolve.
Clever way to get this out of the way.
(7) This section contains the references from every chapter of this book.
The Prehistory of C++
1.1 Simula and Distributed Systems
Dissertation work inspired development Simula inspired improvements to C language for simulating distributed computing emphasizing well-delimited modules.
(19) I was working on my Ph.D. Thesis in the Computing Laboratory of Cambridge University in England. My aim was to study alternatives for the organization of system software for distributed systems. . . . The details of this work and its outcome are of little relevance to C++. What is relevant, though, was the focus on composing software out of well-delimited modules and that the main experimental tool was a relatively large and detailed simulator, I wrote for simulating software running on a distributed system.
1.3 General Background
Gradual change the underlying philosophy, after allusions to differing attitudes toward non-programmer philosophers Aristotle, Pascal, Kierkegaard, Hegel, Camus as important as Knuth and others who are technologists.
(24) The underlying view is that it is possible to achieve improvements through gradual change. The ideal situation is that it is possible to achieve improvements through gradual change. The ideal situation is to maintain the greatest rate of change that improves the welfar of the individuals involved. The main difficulties are to determine what constitutes progress, to develop techniques to smooth transitions, and to avoid excesses caused by over-enthusiasm.
C with Classes
2.1 The Birth of C with Classes
Emphasis on program organization over application areas reflected in offloading to libraries rather than specifying extensions in the language.
(28) The language thus provided general mechanisms for organizing programs, rather than support for specific application areas. . . . Thus, C++ does not have built in complex number, string, or matrix types, or direct support for concurrency, persistence, distributed computing, pattern matching, or file system manipulation, to mention a few of the most frequently suggested extensions. Instead, libraries supporting those needs exists.
C solved problem of computation, so better
organization must cost in run-time overhead.
(28) C with Classes was explicitly designed to allow better organization of programs; “computation” was considered a problem solved by C. I was very concerned that improved program structure was not achieved at the expense of run-time overhead compared to C.
Weinberg would agree with this set of restraints on programming languages against forcing users; compare to striations since Stroustrup, while fan of Kierkegaard, has so far made no allusions to Deleuze and Guattari.
(29) C allows low-level operations, such as bit manipulations and choosing between different sizes of integers. There are also facilities, such as explicit unchecked type conversions, for deliberately breaking the type system. C with Classes and later C++ follows this path by retaining the low-level and unsafe features of C. In contrast to C, C++ systematically eliminates the need to use such features except where they are essential and performs unsafe operations only at the explicit request of the programmer. I strongly felt then, as I still do, that there is no one right way of writing every program, and a language designer has no business trying to force programmers to use a particular style. The language designer does, on the other hand, have an obligation to encourage and support a variety of styles and practices that have proven effective and to provide language features and tools to help programmers avoid the well-known traps and pitfalls.
2.2 Feature overview
(29-30) Since a preprocessor was used for the implementation of C with Classes, only new features (that is, features not present in C) had to be described and the full power of C was available to users.
C with Classes seemed a dialect of C; did not support OOP until virtual functions.
(30) C with Classes was still seen as a dialect of C rather than as a separate language. Furthermore, classes were referred to as “an abstract data type facility.” Support for object-oriented programming was not claimed until the provision of virtual functions in C++ in 1983.
Use of example class stack code to present concept implies internalization of procedural rhetoric familiar to programmers.
Definition of class as user-defined data type specifying representation, operations, and access.
(30-31) Many aspect of the C with Classes calls concept can be observed by examining a simple example from [Stroustrup, 1980]: . . . A class is a user-defined data type. A class specifies the type of class members that define the representation of a variable of the type (an object of the class), the set of operations (functions) that manipulate such objects, and the access users have to these members. . . . Sever key design decisions are reflected here.
2.5.1 Simple-Minded Implementations
Fostering self-sufficiency and local expertise rather than dependence on central support organization.
(37) 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 organizations must follow the opposite strategy. They keep users dependent on services that generate revenues for a central support organization, consultants, or both. In my opinion, this contrast is a fundamental difference between C++ and many other languages.
2.12.1 Overloading of Assignment
Implementing check to handle self-assignment correctly as example of finesse in a programming language that may have kept logicians busy trying to handle via formal language syntax alone.
(59) The [Stroustrup,1982] version uses an example that checks for this==from to handle self-assignment correctly. Apparently, I learned that technique the hard way.
2.14 Work Environment
Example of Weinberg egoless programming in Bell Labs?
(61) Had it not been for the insights of members of the center and the insulation from political nonsense, the design of C++ would have been compromised by fashions and special interests and its implementation bogged down in a bureaucratic quagmire. It was also most important that Bell Labs provided an environment where there was no need to hoard ideas for personal advancement.
Importance of writing tutorial.
(61) Writing a tutorial was considered an essential design tool, because if a feature cannot be explained simply, the burden of supporting it will be too great.
Blackboard-scale examples shaped thinking to focus on archetypical problems, becoming part of C++ folklore.
(62) Since the main design work for C
with Classes and C++ was done on blackboards, the thinking tended to
focus on solutions to “archetypical” problems: small examples
that are considered characteristic for a large class of problems.
Thus, a good solution to the small example will provide significant
help in writing programs dealing with real problems of that class.
Many of these problems have entered the C++ literature and folklore
through my use of them as examples in my papers, books, and talks.
For C with Classes, the example considered most critical was the task
class that was the basis of the task-library supporting Simula-style
simulation. Other key classes were queue, list, and histogram
classes. The queue and list classes were based on the idea –
borrowed from Simula – of providing a link class from which users
derived their own classes.
(62) The danger inherent in this approach is to create a language and tools that provide elegant solutions to small selected examples, yet don't scale to building complete systems or large programs. This was counteracted by the simple fact that C with Classes (and later C++) had to pay for itself during its early years.
Contra product mentality, working closely with users and keeping smaller promises.
(62) Being an individual working closely with users also gave me the freedom to promise only what I could actually deliver, rather than having to inflate my promises to the point where it would appear to make economic sense for an organization to allocate significant resources to the development, support, and marketing of “a product.”
The Birth of C++
3.1 From C with Classes to C++
Need to transition from medium success to larger scale support; compare to study of Lua language development by Takhteyev.
(63) During 1982 it became clear to me that C with Classes was a “medium success” and would remain so until it died. I defined a medium success as something so useful that it easily paid for itself and its developer, but not so attractive and useful that it would pay for a support and development organization. Thus, continuing with C with Classes and its C preprocessor implementation would condemn me to support C with Classes indefinitely.
Cfront a traditional compiler front end that turned out to be fit for PC memory requirements.
(66) The Cfront
front-end for the C84 language was designed and implemented by me
between the spring of 1982 and the summer of 1983.
(66) Cfront was (and is) a traditional compiler front-end that performs a complete check of the syntax and semantics of the language, builds an internal representation of its input, analyzes and rearranges that representation, and finally produces output suitable for some code generator. The internal representation is a graph with one symbol table per scope. The general strategy is to read a source file one global declaration at a time and produce output only when a complete global declaration has been completely analyzed.
(66) I measured Cfront and found that its memory usage leveled out a about 600 Kbytes on a DEC VAX just about independently of which real program I fed it. This fact was what made my initial port of Cfront to a PC/AT in 1986 feasible. At the time of Release 1.0 in 1985 Cfront was about 12,000 lines of C++.
3.3.2 Parsing C++
Did not develop preferred recursive descent parser on advice of mentors, but needs lexical trickery beyond YACC grammar.
(68-69) In 1982 when I first planned Cfront, I wanted to use a recursive descent parser because I had experience writing and maintaining such a beast, because I liked such parsers' ability to produce good error messages, and because I liked the idea of having the full power of a general-purpose programming language available when decisions had to be made in the parser. However, being a conscientious young computer scientist I asked the experts. Al Aho and Steve Johnson were in the Computer Science Research Center and they, primarily Steve, convinced me that writing a parser by hand was most old-fashioned, would be an inefficient use of my time, would almost certainly result in a hard-to-understand and hard-to-maintain parse, and would be prone to unsystematic and therefore unreliable error recovery. The right way was to use an LALR(1) parser generator, so I used A1 and Steve's YACC.
3.5 Virtual Functions
Core of OOP expressed in discussion of virtual functions for shapes.
(73) The problem is that there is no distinction between the general properties of any shape (a shape has a color, it can be drawn, etc.) and the properties of a specific shape (a circle is a shape that has a radius, is drawn by a circle drawing function, etc.). Expressing this distinction and taking advantage of it defines object-oriented programming.
3.13 Tools for Language Design
Extreme difficulty of formal language definition without formal definition method resulting from beginning with C syntax.
(103) Theory and
tools more advanced than a blackboard have not been given much space
in the description of the design and evolution of C++. I tried to use
YACC (an LALR(1) parser generator) for the grammar work, and was
defeated by C's syntax. I looked at denotational semantics, but was
again defeated by quirks in C.
(103) My conclusion is that a formal definition of a language that is not designed together with a formal definition method is beyond the ability of all but a handful of experts in formal definition.
Famous statement that languages are grown, not merely designed, taking input from experienced professionals considering real applications, with practical balancing of needs, ideals, techniques, constraints.
(104) Unfortunately, you usually cannot conduct proper experiments either. . . . As far as possible, I relied on the opinions of experienced programmers considering real applications only. . . . I firmly believe that language design isn't an exercise in pure thought, but a very practical exercise in balancing needs, ideals, techniques, and constraints. A good language is not merely designed, it is grown. The exercise has more to do with engineering, sociology, and philosophy than with mathematics.
3.15 The Whatis? Paper
Multi-paradigm nature of C++ reaffirmed in Whatis paper.
The significance of this paper is that it is the first exposition of
the set of techniques that C++ was aiming to provide support for. All
previous presentations, to avoid dishonesty and hype, had been
restricted to describe what features were already implemented and in
(106) The result was a reaffirmation of the importance of the “multi-paradigm” nature of C++. . . . The importance of static type checking was also strongly emphasized. In other words, C++ follows the Simula rather than the Smalltalk model of inheritance and type checking.
Design reflection on importance of statically type-checked parts.
(107) This is partly a special case of the general notion that what can be guaranteed by machine and from general rules shouldn't be done by people and by debugging. Naturally, it also helps debugging. However, the most fundamental reason for relying on statically checked interfaces was that I was – as I still am – firmly convinced that a program composed out of statically type-checked parts is more likely to faithfully express a well-thought-out design than a program relying on weakly-typed interfaces or dynamically-checked interfaces.
C++ Language Design Rules
4.1 Rules and Principles
Rules give way to practical experience in design of C++.
(109) My rules for the design of C++ most certainly have exceptions. In fact, if a rule and practical experience are in conflict, the rule gives way.
4.2 General Rules
General rules focus on current generation solving current problems on current systems of mid 1980s for general rules: driven by real problems, avoiding quest for perfection, be useful now, obvious implementation for every feature, provide transition path, language not complete system, comprehensive support for supported styles, avoid forcing people.
(110) The most general and most important C++ rules have little to do with language-technical issues. They are almost sociological in their focus on the community C++ servers. The nature of the C++ language is largely determined by my choice to serve the current generation of systems programmers solving current problems on current computer systems.
Appeals to the average to be useful now, but changes anticipating likely trends.
(111) C++ must be useful now:
Most programming is relatively mundane, done in relatively
low-powered computers, running relatively dated operating systems and
tools. Most programmers have less formal training than they would
have liked and most have insufficient time to upgrade their
knowledge. To serve these programmers, C++ must be useful to someone
with average skills, using an average computer.
(111) The meaning of this rule – like most of the others – changes with time and partly as a result of C++'s success. . . . This implies that features requiring more computer resources and more maturity from programmers can and must be considered. Exception handling and run-time type identification are examples of this.
4.3 Design Support Rules
Higher-level ideas for thinking and expression: support sound design, program organization, more declarative, affordable features, allow useful feature over preventing misuse, composition from separately developed parts.
(114) The rules listed here relate primarily to C++'s role in supporting design based on notions of data abstraction and object-oriented programming. That is, they are more concerned with the language's role as a support for thinking and expression of high-level ideas than its role as a “high-level assembler” along the lines of C or Pascal.
Locality and terseness help fit code chunks on a screen for easier understanding.
(118) Finally, code is easier to understand and manipulate if significant chunks fit on a screen. C's traditional terseness helps here, and the C++ rules that allow new variables to be introduced where they are first needed is a further step in this direction.
4.5 Low-Level Programming Support Rules
Low-level programming support rules: use traditional dumb linkers, no gratuitous incompatibilities with C, leave no room for another lower-level language, zero overhead, provide manual control.
(120) Using traditional linkers makes it relatively easy to maintain link compatibility with C. This is essential for smooth use of operating system facilities, for using C, Fortran, etc., and for writing code to be used as libraries from other language. Using traditional linkers is also essential for writing code intended to be part of the lower levels of a system, such as device drivers.
5.2 Release 2.0
Compare narrative about second major release and plan for new phase of support and development to Lua story researched by Takhteyev.
By mid-1986, the course for C++ was set for all who cared to see. The
key design decisions were made. The direction of the future evolution
was set with the aim for parameterized types, multiple inheritance,
and exception handling. . . . At this point, C++ had about 2,000
(124) This was the point where the plan – as originally conceived by Steve Johnson and me – was for a development and support organization to take over the day-to-day work on tools (primarily Cfront), thus freeing me to work on the new features and the libraries that were expected to depend on them. This was also the point where I expected first AT&T and then others to start building compilers and other tools that eventually would make Cfront redundant.
Blames poor management for derailing plan for corporate efforts to build compilers and other tools, along with personal stubbornness.
(124-125) Actually, they had already started, but the good plan was soon derailed due to development management indecisiveness, ineptness, and lack of focus. . . . However, my wish for direct support for templates still blinded me to alternatives. There was also a misguided belief among some development managers that the library might become both a standard and a significant source of income.
Survey of primary actors for design, coordination, coding, testing and documentation; previous reader noted, you sure got enough credit, bonehead.
(125) Release 2.0 was the work of a group consisting of Andrew Koenig, Barbara Moo, Stan Lippman, Pat Philip, and me. Barbara coordinated; Pat integrated; Stan and I coded; Andy and I evaluated bug reports and discussed language details; Andy and Barbara did the testing. In all, I implemented all of the new features and something like 80% of the bug fixes for 2.0. In addition, I wrote most of the documentation.
5.2.1 Feature Overview
Philosophers of programming should understand these language features for their design consequences along with sociological aspects of technology.
(126) The main features of 2.0 were first presented in [Stroustrup,1987c] and summarized in the revised version of that paper [Stroustrup,1989b] that accompanied 2.0 as part of its documentation: Multiple inheritance; Type-safe linkage; Better resolution of overloaded functions; Recursive definition of assignment and initialization; Better facilities for user-defined memory management; Abstract classes; Static member functions; const member function; protected members; Generalized initializers; Base and member initializers; Overloading of operator ->; Pointers to members. . . . Naturally, integrating these features involved significant work, but it was most unfortunate that this was allowed to take priority over the completion of the language as outlined in the “whatis” paper.
Litany of contested priorities in standardization; compare to Bowker and Star.
(130) Standardization isn't easy. There are people on the committee who are there to preserve status quo, there are people with an idea of status quo that makes them want to turn the clock back several years, there are people who want to make a clean break from the past and design a completely new language, there are people who care only about a single issue, there are people who care only about a single class of systems, there are people whose votes are tied by their employers, there are people who represent only themselves, there are people with a primarily theoretical view of programming and programming languages, there are people who want a standard now! even if it means some details are left unresolved, there are people who want nothing short of a perfect definition, there are people who come thinking that C++ is a brand new language with hardly any users, there are people who represent users with many millions of lines of code built over a decade, etc. Under the rules of standardization, we all have to more or less agree.
6.1 What is a Standard?
Standard defined as contract between programmer and implementer.
(133) One ideal for a standard is to completely specify exactly which programs are legal and exactly what the meaning of every such program is. For C and C++ at least, that is not the whole story. In fact, it can't and shouldn't be the ideal for languages designed to exploit the diverse world of hardware architectures and gadgets. . . . Thus, a standard is often described as “a contract between the programmer and the implementer.” It describes not only what is “legal” source text, but also what a programmer can rely on in general and what behavior is implementation-dependent.
6.2 How does the Committee Operate?
Voting rules for national and international standards committees, ANSI like lower house and ISO upper house; clear American dominance.
There are actually several committees formed to standardize C++. The
first and largest is the American National Standards Institute's
ANSI-X3J16 committee. That committee is the responsibility of the
Computer and Business Equipment Manufacturers Association, CBEMA, and
operates under its rules. . . . Officially, the most important
committee is the International Standards Organization's
(136) Basically, we have decided not to accept anything that doesn't pass under both ANSI and ISO voting rules. This implies that the committee operates rather like a bicameral parliament with a “lower house” (ANSI) doing most of the arguing and an “upper house” (ISO) ratifying the decisions of the lower house provided they make sense and duly respect the interests of the international community.
Committees meet jointly three times yearly, with current working groups using email to handle workload.
The ANSI and ISO committees meet jointly three times a year.
(137) The current working groups are: C compatibility, Core language, Editorial, Environment, Extensions, International issues, Libraries, Syntax. Clearly, there is too much work for the committee to handle in only three weeks of meetings a year, so much of the actual work goes on between meetings. To aid communication, we use email a lot.
Public forum better for addressing extension activity than marketplace mechanisms, where the language would fracture into dialects.
(147-148) My personal opinion is that extension activity of various sorts is inevitable, and it is better to have it out in the open and conducted in a semi-civilized manner in a public forum under somewhat formal rules. The alternative is a scramble to get ideas accepted through the mechanisms of attracting users in the marketplace. That mechanism isn't conducive to clam deliberation, open discussion, and attempts to serve all users. The result would be the language fracturing into dialects.
6.5.2 Restricted Pointers
Restricted pointers shunned in C after Ritchie lambasted the noalias proposal by the ANSI committee and prevented its acceptance.
(157) A Fortran compiler is allowed to
assume that if a function is given two arrays as arguments, then
those arrays don't overlap. A C++ function is not allowed to assume
that. The result is an advantage in speed for the Fortran routing of
between 15% and 30 times dependent on the quality of the compiler and
the machine architecture. The spectacular savings come from
vectorizing operations for machines with special vector hardware such
(157) Given C's emphasis on efficiency, this was considered an affront and the ANSI C committee proposed to solve the problem by a mechanism called noalias to specify that a C pointer should be considered alias-free. Unfortunately, the proposal was late and so half-baked that it provoked Dennis Ritchie to his only intervention in the C standards process. He wrote a public letter stating, “noalias must go; this is non-negotiable.”
126.96.36.199 Extended Character Sets
Worries about portability and comprehension if non-comment code is written using extended character sets reflects hegemony of English as common language for programmers; same point made about Portuguese in Takhteyev.
Later vision of internal non-textual representation of program code could permit expression in multiple human languages.
(161) I worry about portability and comprehension, though. The technical portability problem can be handled. However, English has an important role as a common language for programmers, and I suspect that it would be unwise to abandon that without serious consideration. To most programmers, a systematic use of Hebrew, Chinese, Korean, etc., would be a significant barrier to comprehension. Even my native Danish could cause some headaches for the average English-speaking programmer.
Interest and Use
7.1.1 Lack of C++ Marketing
First language to develop large user mass and dissemination of information through email, newsgroups and other electronic networks, without traditional marketing.
(164) To me, the most surprising thing about these numbers is that early users were gained without the benefit of traditional marketing. Instead, various forms of electronic communication played a crucial role in this. In the early years, most distribution and all support was done using email. Relatively early on, newsgroups dedicated to C++ were created by users. This intensive use of networks allowed a wide dissemination of information about the language, techniques, and the current state of tools. These days this is fairly ordinary, but in 1981 it was relatively new. I suspect C++ was the first major language to take this path.
Do not bother learning Smalltalk, reiterating good object-oriented design styles take advantage of static type system, whereas a Smalltalk initiation to OOP with dynamic casting will lead to unsafe and ugly casting in C++.
I want to do OOP, should I learn Smalltalk before C++?
. . . In fact, unless you have the time to learn and digest both the
Smalltalk and the C++ concepts and techniques, using Smalltalk as a
learning tool can lead to poor C++ designs.
(170) The point here is that styles that are appropriate and well supported in Smalltalk are not necessarily appropriate for C++. In particular, a slavish following of Smalltalk style in C++ leads to inefficient, ugly, and hard-to-maintain C++ programs. The reason is that good C++ requires design that takes advantage of C++'s static type system rather than fights it. Smalltalk supports a dynamic type system (only) and that view translated into C++ leads to extensive unsafe and ugly casting.
Learn bottom-up, do not bypass learning traditional procedural programming concepts, for which the C foundation of C++ excels.
(171) Should I start using C++ as an
OOPL or as a better C? . . . In
my experience, the safest bet is to learn C++ bottom-up, that is,
first learn the features C++ provides for traditional procedural
programming, the better-C subset, then learn to use and appreciate
the data abstraction features, and then learn to use class
hierarchies to organize sets of related classes.
(171) It is – in my opinion – dangerous to rush through the earlier stages because there is too high a probability of missing some key point.
Education, not just training, is required to learn new design concepts.
C++ isn't just a new syntax for expressing the same old ideas – at
least not for most programmers. This implies a need for education,
rather than mere training.
(172) The overwhelming experience is that taking the time and making the effort to learn the key data abstraction and object-oriented techniques is worthwhile for almost all programmers and yields benefits not just in the very long run but also within three to twelve months.
OOP and OOD are practical rather than theoretical; recommends Booch text, noting use of five languages for examples somewhat avoids language bigotry, although footnote that second edition uses C++ examples throughout.
Concern that toy examples can make dangerous religions of OOD must be balanced against treatment by Tanaka-Ishii, for example being versus becoming.
(172) How long does it take to learn
C++? . . . Object-oriented
programming and object-oriented design are essentially practical
rather than theoretical disciplines. Unapplied or applied only to toy
examples, these ideas can become dangerous “religions.”
(172) Note that learning C++ is then primarily learning programming and design techniques, not language details. Having worked through a good textbook I would suggest a book on design such as [Booch,1991], which has nice longish examples in five different langauges (Ada, CLOS, C++, Smalltalk, and Object Pascal) and is therefore somewhat immune to the language bigotry that mars some design discussions.
Real competition is between user communities rather than individual language features and specifications.
(179) The real competition is not a beauty contest between individual language features or even between complete language specifications, but a contest between user communities in all their aspects, all their diversity, and all their inventiveness. A well-organized user community united by a grand idea has a local advantage, but is in the longer run and in the larger picture at a severe disadvantage.
Stroustrup, Bjarne. The Design and Evolution of C++. Reading, MA: Addison-Wesley Publishing Company, 1994. Print.