Previous | Table of Contents | Next |
6.2.4.5. Syntax Problems
Could I have fixed the most annoying deficiencies of the C syntax and semantics at some point before C++ was made generally available? Could I have done so without removing useful features (to C with Classess users in their environmentsas opposed to an ideal world) or introducing incompatibilities that were unacceptable to C programmers wanting to migrate to C with Classes? I think not. In some cases, I tried, but I backed out my changes after complaints from outraged users. The part of the C syntax I disliked most was the declaration syntax. Having both prefix and postfix declarator operators cause a fair amount of confusion. So does allowing the type specifier to be left out (meaning int by default). In 1995, the C++ standards committee finally banned implicit int in declarations. However, the unfortunate declarator syntax remains unchanged.
My eventual rationale for leaving things as they were was that any new syntax would (temporarily at least) add complexity to a known mess. Also, even though the old style is a boon to teachers of trivia and to people wanting to ridicule C, it is not a significant problem for C programmers. In this case, Im not sure if I did the right thing, however. The agony to me and other C++ implementers, documenters, and tool builders caused by the perversities of syntax has been significant. Users canand doof course insulate themselves from such problems by writing in a small and easily understood subset of the C/C++ declaration syntax.
A significant syntactic simplification for the benefit of users was introduced into C++ at the cost of some extra work to implementers and some C compatibility problems. In C, the name of a structure, a structure tag, must always be preceded by the keyword struct. Heres an example:
struct buffer a; /* struct is necessary in C */
In the context of C with Classes, this had annoyed me for some time because it made user-defined types second-class citizens syntactically. Given my lack of success with other attempts to clean up the syntax, I was reluctant and only made the changeat the time where C with Classes was mutated into C++at the urging of Tom Cargill. The name of a struct or a class is now a type name and requires no special syntactic identification:
buffer a; // C++
The resulting fights over C compatibility lasted for years (see also section 6.3.4).
6.2.4.6. Derived Classes
The derived class concept is C++s version of Simulas prefixed class notion and thus a sibling of Smalltalks subclass concept. The names derived class and base class were chosen because I never could remember what was sub and what was super and observed that I was not the only one with this particular problem. It was also noted that many people found it counterintuitive that a subclass typically has more information than its superclass. In inventing the terms derived class and base class, I departed from my usual principle of not inventing new names where old ones exist. In my defense, I note that I have never observed any confusion about what is base and what is derived among C++ programmers and that the terms are trivially easy to learn, even for people without a grounding in mathematics.
The C with Classes concept was provided without any form of runtime support. In particular, the Simula (and C++) concept of a virtual function was missing. The reason for this was that Iwith reason I thinkdoubted my ability to teach people how to use them and even more my ability to convince people that a virtual function is as efficient in time and space as an ordinary function as typically used. Often, people with Simula and Smalltalk experience still dont quite believe that until they have had the C++ implementation explained to them in detailand many still harbor irrational doubts after that.
Even without virtual functions, derived classes in C with Classes were useful for building new data structures out of old ones and for associating operations with the resulting types. In particular, as explained in Classes: An Abstract Data Type Facility for the C Language (Stroustrup, 1980a) and Adding Classes to the C Language: An Exercise in Language Evolution (Stroustrup, 1982), they allowed list classes to be defined and also task classes (that is, concurrency-support classes).
In the absence of virtual functions, a user could use objects of a derived class and treat base classes as implementation details (only). Alternatively, an explicit type field could be introduced in a base class and used together with explicit type casts. The former strategy was used for tasks where the user sees only specific derived task classes and the system sees only the task base classes. The latter strategy was used for various application classes where, in effect, a base class was used to implement a variant record for a set of derived classes. Much of the effort in C with Classes and later C++ has been to ensure that programmers neednt write such code. Most important in my thinking at the time and in my own code was the combination of base classes, explicit type conversions, and (occasionally) macros to provide generic container classes. Eventually, these techniques matured into C++s template facility and the techniques for using templates together with base classes to express commonality among instantiated templates (section 6.6.3).
Previous | Table of Contents | Next |