[net.lang.c++] the C++ scope operator

rose@think.ARPA (John Rose) (02/27/86)

(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

keith@cecil.UUCP (keith gorlen) (02/28/86)

>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

I agree.  I've been hacking around this by using #define BASE and
#define THIS as identifiers for the base class and this class,
respectively.  When I want to refer to a specific class, I use class::
and when I want to refer to the base class I use BASE::.

>(Multiple inheritance anyone?  Anybody thinking about it besides me?
>That's a subject for another posting.)

Bye-bye efficiency -- not to mention comprehensibility!  It's not
worth it!  Maybe in a special dialect called C++Flavors.
-- 
---
	Keith Gorlen
	Computer Systems Laboratory
	Division of Computer Research and Technology
	National Institutes of Health
	Bethesda, MD 20892
	phone:	(301) 496-5363
	uucp:	{decvax!}seismo!elsie!cecil!keith

bs@alice.UucP (Bjarne Stroustrup) (02/28/86)

> Subject: the C++ scope operator

> Path: ..!think!rose (John Rose @ Thinking Machines, Cambridge, MA)

> (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.

That similarity is puly accidental.

> 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.


In Common Lisp, that 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.

Thanks, but note that (3) is not  C++: ``::'' simply allows you to
state the full name of something. If that something happens to be
private it is still private even if you use ``::''.

	- Bjarne Stroustrup (AT&T Bell Labs, Murray Hill)

P.S. and yes, I know there are problems with expressing a reference to a
base class using the ``class_name::member_name'' notation (as opposed
to a ``relative address'' notation, for example ``base::member_name''),
but it does have one advantage: it scales to handle multiple inheritance.

mark@umcp-cs.UUCP (Mark Weiser) (03/01/86)

In article <54@cecil.UUCP> keith@cecil.UUCP writes:
>
>Bye-bye efficiency -- not to mention comprehensibility!  It's not
>worth it!  Maybe in a special dialect called C++Flavors.

I don't agree.  There should be absolutely no efficiency loss, 
and the comprehensibility is much better in some cases because
of better modularity and code reusability.  Naturally any new feature
provides a new way to write bad code, but that is not a fair attack.
So did the old features.
-mark
-- 
Spoken: Mark Weiser 	ARPA:	mark@maryland	Phone: +1-301-454-7817
CSNet:	mark@umcp-cs 	UUCP:	{seismo,allegra}!umcp-cs!mark
USPS: Computer Science Dept., University of Maryland, College Park, MD 20742