Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!munnari!otc!mikem From: mikem@otc.oz (Mike Mowbray) Newsgroups: comp.lang.c++ Subject: C++ Confusing?? (was Objective-C vs C++) Message-ID: <259@otc.oz> Date: Sun, 27-Sep-87 00:09:53 EDT Article-I.D.: otc.259 Posted: Sun Sep 27 00:09:53 1987 Date-Received: Mon, 28-Sep-87 01:43:56 EDT References: <3405@ece-csc.UUCP> <638@its63b.ed.ac.uk> <1811@watcgl.waterloo.edu> <1414@pdn.UUCP> Organization: OTC Development Unit, Australia Lines: 117 In article <1414@pdn.UUCP>, ken@pdn.UUCP (Ken Auer) says: >> me is that the additional features of C++ (over C) are invoked using >> syntax that looks like the rest of C, while .... > ^^^^^^^^^^^^^^^^^^^^^^^^ > "Looks like" are the key words here. > > var1 << var2; > > *looks like* C code which means "logically shift var1 left var2 bits". > However in C++ it COULD mean "put var2 onto outputStream var1". C++ > also uses ampersands (&) for more purposes than standard C does, [....] > The point is that some of the extensions to C by C++ can be extremely > confusing until you carefully examine the context of some of these symbols. Similarly, in article <308@koel.rmit.oz>, Paul Menon says: > C++ further confuses the issue with overloading, etc. Hold it. The idea that operator overloading is confusing is only indicative of poor design of the classes. It is very tempting to use operator overloading because it "looks elegant", but this is easy to abuse. No one would say that operator+(complex, complex) is hard to understand. Similarly, the use of << for ostreams is quite elegant and matches one's intuitive idea of what class ostream is doing. These days, I advise people to apply considerable restraint on their use of operator overloading because I'm aware of this tendency to abuse. This does not mean that it's inherently confusing. Rather it means that people can (and do) misuse it. This is true of all programming;- misleading function names have exactly the same effect. BTW, I've found the use of &'s in C++ to be quite logical once you understand what a reference really is. -------------------------------------------------------------------------- In article <77300003@uiucdcsp> johnson@uiucdcsp.cs.uiuc.edu says: > The major problem with C++ is the lack of a class library. AT&T is > shooting themselves in the foot by not providing one. Incorrect. I've heard that they have various libraries internally, but are reluctant to release them because it's so hard to write a good library, and once they release something it's effectively set in concrete. So I would say they are doing an excellent long-term service to the rest of us by holding out until they're happy that their libraries are *right*. Sure, it means that we have to do the work ourselves for the time being, but as Keith Gorlen has shown, (and as I've found in our own OTC libraries), it's not really an difficult task to build up a collection of useful stuff in a reasonable period of time. A further point is that with the advent of multiple inheritance for C++, (and hopefully its not-too-distant commercial availability) the optimum structure for libraries will change. Arrangements that were best for single inheritance may not be best for multiple inheritance, or work-arounds that were required for SI are no longer need in MI. > The major advantage of o-o programming is software reuse, but reusable > software is ten times as hard to write as software than merely works, so it > is entirely unreasonable to expect local programmers to produce it. An > object-oriented language needs an extensive class library to be successful. But things must start somewhere. The point about re-usability is that the libraries are developed over a period of time, relying heavily on feedback for their evolution. I would like to see more discussion on what people have done in writing various general-purpose C++ library classes and what makes libraries good and bad. -------------------------------------------------------------------------- To kick such a discussion off, here's one thought I had recently on a difference in how one might design a general hash mechanism in SI and MI: Suppose we want a general HashTable class. The things to go in it would all need some kind of hash(int) member function. (E.g: a string might have a hash(int i) that just added up the char values and % i'd the result, etc.) In SI, this tends to imply that you must have a class Hashed, say: struct Hashed { virtual int hash(int); }; and class HashTable could have members like install(Hashed&), remove(Hashed&), etc, the idea being that one derives specific Tables from HashTable, and puts things on it that were derived from Hashed. In the SI case, I've found this to be unsatisfactory, because anything that is going on a HashTable must be derived from Hashed. This is a pain if you're working with a class that is already derived from something else, and you don't have access to the base classes. If everything is derived from some base class Object, it can have a hash() member, but this defeats reusabilty, I feel, since reusability implies a way of coping with the fact we *can't* know everything in advance. Therefore, I've resorted to using a less elegant mechanism whereby each HashTable is constructed with a "hashfunction" argument. I.e: it's told what function to use. (A hashfunction just takes a void* and an int.) This results in not having strong type checking, but basically seems safe enough with a bit of care. So when someone wants a specific Hashing arrangement, they just declare the hash function, and pass it to the HashTable constructor, etc. The point of all this is that in an MI environment, the former method becomes attractive again, since one can easily derive from both Hashed and something else. (Actually, I guess one would derive virtually from Hashed.) Mike Mowbray Systems Development |||| OTC || ACSnet: mikem@otc.oz UUCP: {uunet,mcvax}!otc.oz!mikem Phone: (02) 287-4104 Snail: GPO Box 7000, Sydney 2001, Australia