Xref: utzoo comp.object:3585 comp.lang.c++:13655 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!think.com!zaphod.mps.ohio-state.edu!wuarchive!udel!haven.umd.edu!mimsy!panache.cs.umd.edu!davew From: davew@panache.cs.umd.edu (David G. Wonnacott) Newsgroups: comp.object,comp.lang.c++ Subject: Re: C++ and waitresses Message-ID: <34867@mimsy.umd.edu> Date: 25 May 91 01:04:13 GMT References: <2326@media03.UUCP> Sender: news@mimsy.umd.edu Reply-To: davew@panache.cs.umd.edu (David G. Wonnacott) Followup-To: comp.object Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 140 In article <2326@media03.UUCP> pkr@media03.UUCP (Peter Kriens) writes about the difficulties of using a language or eating in a restaurant that offers many choices. In defense of the way of life here in the U.S.A., let me point out that there are some advantages of the long menu of C++ features. For example, consider inheritance. Smalltalk has one inheritance mechanism. C++ forces the programmer to choose between public or private inheritance (some compilers may allow "protected" inheritance for orthogonality, but I do not see it listed in section 11.2 of my A.R.M.). I have seen smalltalk programmers confuse the use of inheritance to share behavior (i.e. for subtyping) with the use of inheritance to share implementation. Some are not aware of the difference between these concepts, and some simply have a hard time telling which is being used in a given piece of code, since they are both expressed by the word "subclass." A C++ programmer is forced to choose public or private derivation, but this choice should be easy once you have learned to use public derivation to share behavior, and private derivation (or inclusion of private data members) for sharing implementation. If you do not know whether you are creating a subclass to share the behavior or implementation, I suspect that the language is not the problem. If you have not learned which C++ mechanism to use for each of these needs, blame your teacher (my apologies to my students who learned C++ from me in the dark days before I figured this out). Furthermore, other C++ programmers who look at a class derivation can tell quickly whether the subclass is meant to be used in a context where the superclass is expected. The compiler even prevents the use of an object of a privately derived class where a base class type object is needed. Unfortunately, the compiler can not ensure that a publicly derived class is a subtype of its base. A C++ programmer who learns Smalltalk or CLOS or as a 2nd language may be distressed to find that there is no way to express the distinction between a subtype and a subclass that can not be substituted safely for its base. One could add a "publicSubclass" message to Smalltalk, to make this distinction clear, but that is no help for existing code. On the other hand, a friend of mine who does most of his programming in Lisp Flavors complains that C++'s multiple inheritance mechanism is not flexible enough: there's no way to control method combination. This friend is Canadian -- but perhaps he likes complicated menus because his mind was warped by going to school here in the states ;-) On another point: >Why in the world would anybody >want to write an Array class for different types? Because an array of floats is not the same type as an array of strings: I can store the value "hello world" on one, but not the other. Just as I can use "hello world" as an argument to a function with string parameter, but I can not use it as an argument to sqrt. Declaring the variable types can be a pain, but static type checking is a fast relatively easy way to detect a lot of bugs. This is especially important in a large project with many programmers. > They will >all use the same algorithm, dont they? So why should you >be forced to spell out on which type you want it to >operate? You shouldn't. Thats what a parameterized type is all about. You define array once, and the system lets you create objects of type array or array. The need for a parameterized type mechanism is not unique to C++: Any statically typed language that allows the creation of new types (such as Ada, Eiffel, TS, or C++) must provide one, or the programmer will be forced to do all sorts of gross things to circumvent the type system. Given that C++ is statically typed, do you think a parameterized type mechanism should be added to it? Or would you rather not complicate the language definition, and go on without a good way of defining linked lists? In summary, there are good reasons to have some of these features in the language definition. There is more flexibility in a system that provides a few powerful mechanisms for you to build on, but there are times when it is better to build a variety of options into the compiler. It is hard to add static type checking to a dynamically typed, but extensible, language. If a language definition provides only one mechanism for something like inheritance, the use of that mechanism for several purposes may lead to confusion of these purposes, or at least difficulty in deciding which is meant in a given piece of code. It may or may not be harder to learn to use these mechanisms than to learn to use one mechanism for several purposes, but at least the confusion decreases as you become familiar with them. I am not saying that C++ is the perfect tool for all purposes. There are definitely some choices that are, to say the least, very annoying. For example, the need for the programmer to declare methods or superclasses "virtual," based on a guess about how the class will be used. But this is necessary to maintain the efficiency of C++ -- just because efficiency is not important to you, don't assume it isn't important to anyone else. The argument that computers are 40 times faster than they were 13 years ago isn't relevant unless people expect less than 40 times as much -- how many machines had to push around each bit of the image of each character they displayed, or clip their output to fit into a certain region on the screen in 1978? How many PC's were expected to run several 100K+ programs concurrently? > I will use it, but I will always have a feeling >that it could have been much easier if choices were made >on performance instead of just marketing. This is an inaccurate desription of the work of Bjarne Stroustrup and others within AT&T. I believe that Stroustrup's decisions are based on his estimation of the technical merits, not the marketability, of different options. You may not agree with his design goals (micro-efficiency, preservation of "the character of C" in C++), but don't accuse him of putting sales before technical merit unless you have some evidence of his doing so. Please note again that I do not think C++ is the right tool for every problem. I suspect Stroustrup does not believe this either. I often use Lisp or Smalltalk, but when I do, there are things I miss from C++. Please also note that, with the exception of the paragraph preceding this one, this message is not meant as a flame of the original posting, but a discussion of the reasons for some of the choices available in C++. -- David Wonnacott davew@tove.cs.umd.edu Although the moon is smaller than the earth, it is further away.