Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/17/84; site think.ARPA Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!rose From: rose@think.ARPA (John Rose) Newsgroups: net.lang.c++ Subject: the C++ scope operator Message-ID: <4438@think.ARPA> Date: Thu, 27-Feb-86 11:21:25 EST Article-I.D.: think.4438 Posted: Thu Feb 27 11:21:25 1986 Date-Received: Sat, 1-Mar-86 04:19:11 EST Distribution: net Organization: Thinking Machines, Cambridge, MA Lines: 76 (Thanks for the feedback.) What are some plausible uses of the scope operator "::"? Here are a few: (1) Definitions of members outside the main declaration. (2) Invoking an inherited member function. (3) Random violations of class abstraction. Amusingly, the same "::" syntax is used in Common Lisp for something corresponding to Number 3. Perhaps because of that reinforcement, something in me winces when I see the scope operator used: "Get ready for trouble, because someone's poking their nose where they shouldn't". The scope operator is a danger sign to readers of code, much like the cast is. I think Number 1 doesn't set off those alarms because it occurs in a very specialized context: In a (usually unique) file of definitions, in top-level declarators. But (and this is my main point) Number 2, while syntactically indistinguishable from the alarming Number 3, is a perfectly safe, reasonable, and common operation. Smalltalk calls it "sendSuper". Invoking an inherited handler is a necessary operation in many (most?) abstractions which are specializations. For example, if you have a class queue with a member put(), you can derive a class queue_with_census which "wraps" the generic put() operation with a function which first calls some element-counting function, and then transfers to the inherited put(). Expressing sendSuper as if it were an arbitrary violation of abstraction also has the defect that redundant information must be specified. The name of the parent (base) class is available to the compiler, but the programmer must state it explicitly. This seems unmodular. (Granted, it can't happen in client code.) Here's an example of how the unmodularity could hurt: Suppose class der is derived from class bas, and sendSuper operations are used in der's implementation. Later, as the hierarchy derived from bas gets more complicated, the programmer decides to organize it in two levels. A new "middle" abstraction, class mid, is interposed between bas and der. Now all uses of the scope operation in the code for der must be re-examined to see whether they are intended to mean sendSuper, *and* whether mid now implements the message. In these cases, the name "bas" must be replaced with "mid". This is error-prone. I submit that a more innocuous-looking syntax be conceived for sendSuper, and the requirement be dropped that the parent class be named in the construction. Here's a candidate: der::foo(int m) { // pre-actions return 1+bas::foo(m-1); // Not this, return 1+continue(m-1); // but this. } Two merits: Uses an underused C keyword, and echoes "CONTINUE-WHOPPER" of ZetaLisp. (Yes, that's not much of an echo; sendSuper is more euphonious.) Well, put "sendSuper", in whatever form, on the list of future extensions. Incidentally, it interacts *strongly* with another extension I (and others?) would like to see eventually: Multiple inheritance. In a single-inheritance system, it's annoying for the programmer to calculate the name of the "next class up handling this message"; with multiple inheritance that's next to impossible. (Besides, a single sendSuper may expand to calls to *several* mutually unrelated handlers.) (Multiple inheritance anyone? Anybody thinking about it besides me? That's a subject for another posting.) -- ---------------------------------------------------------- John R. Rose, Thinking Machines Corporation, Cambridge, MA 245 First St., Cambridge, MA 02142 (617) 876-1111 X270 rose@think.arpa ihnp4!think!rose