From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: downcasting (was Re: GOTOo wars)
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Mon, 12 Oct 1992 17:39:08 GMT

In article <407@ulogic.UUCP> hartman@ulogic.UUCP (Richard M. Hartman) writes:
>In article <1992Oct4.114145.21060@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>
>I do not have heterogenous lists, but in order to implement a StudentList
>I have to derive from List, which returns Object * (StudentObj is derived
>from Object, and can thus be placed on an NIH List).  When I get a 
>Student from the List it is an Object * and I have to cast to
>StudentObj *.  I know that all members of the list are going to be
>StudentObj, but I still have to do the stupid downcast because I am
>using SOMEONE ELSE'S List class as a base class.  NIH is the National
>Institute Health (why they produced an object heirarchy library I
>have NO idea).  The NIH class library is the foundation of the book
>"Data Abstraction and Object-Oriented Programming in C++", by
>Keith E. Gorlen, Sanford M. Orlow, Perry S. Plexico.  Published
>by Wiley.
>
>If I were doing my OWN stuff (and my compiler supported templates)
>I could make use of some of this discussion.  However the basic concept
>is that all objects derive from "Object".  Generic container classes
>take members of type "Object" (or, of course, it's descendants). 
>Whether you store homogeneous or heterogenous data in the container
>classes is immaterial.  The container classes only know about 
>Object, and that is what they return when you use the access
>functions.  It is up to you to castdown to the correct type.  The
>original topic here WAS whether castdown actually had any purpose,
>wasn't it?  (it's been so long.....)

	If checked castdowns are added to C++ they would be added
to the current version of the language. Not version 1,
which containing no template mechanism or multiple inheritance
was in my opinion a pale shadow of the current ARM specs.

	NIH was hopefully written for version 1, and is thus
hopelessly out of date. If you are asking whether castdowns
are especially useful in the current C++ the answer is no
IMHO, not especially in well written programs. If you are asking
whether you must use them with your current compiler and NIH
the answer is perhaps yes, but that only makes them an
anachronism IMHO.

>
>>	For a start, you cant have a heterogenous list or array.
>
>I never said I did.
>

	No, but NIH thinks you can. You have to break the type
system because its design is flawed. Thats perhaps because
C++ version 1 was flawed (I'm not saying it wasn't the thing to
do at the time, but that time is past).

>[ discussion about list of union type omitted ]
>
>>	typedef [A,B,C] *T; // tagged pointer type T
>
>I have never seen this mechanism.  Is it related to templates
>(and thus also not supported by my compiler)?

	It is an idea I have proposed as an extension to C++
to support heterogenous aggregates (which you cant really have :-)

>
>>	There is a second type of list one might consider.
>>This list consists of pointers to objects derived from Base.
>>Here, polymorphism/inheritance unifies the type: it homogenises
>>the type. A list of pointers to Base is homogenous, not
>>heteromorphic. After all, all the pointers point to a Base,
>>and every object derived from a Base 'isA' Base (or should be
>>to be used in this type of list).
>
>Ahhhh.  Here we go.  This is what the NIH library does.  

	Not really. Because 'Object' is a useless stub base
that has no useful functions. A list of pointers to Student
might allow for Students that were Science or Arts or
Engineering faculty with differnt implementations of
certain virtual functions declared in Student.

> by NIH's ideas of what is proper.... as I said originally, if
> there is a better way, PLEASE let me know!)

	There is a better way, but it involves abandoning NIH.
It would be better to abandon it now before it causes too
many problems.

>
>>	This second type of list has the added advantage
>>of allowing INDETERMINATE objects derived from base to
>>be pointed to, at the expense of restricting you
>>to interfacing via the Base. (Often facilitated by
>>virtual functions).
>
>Unless you know in advance what the "real" type is.

	No. If that were the case, you would have a list
of the "real" type.

>
>>	In both cases we want sound practice, namely, to access
>>the list elements by the declared interface only. 
>
>Yes.  

	But which NIH wont let you do.
>
>>	The two mechanism can be combined, assuming
>>D1, D2, D3 are derived from Base we can have:
>>
>>	typdef [Base,D1,D2,D3] *T;
>>
>>and use the Base* for polymorphic calls and the D1, D2 and D3 
>>pointers for heteromorphic ones.
>
>Again this construct.  Please explain it further.
>
>For that matter, even if my compiler supports it, how does

	It doesnt, its just an idea for an extension.

>use of "T" differ from use of "Base *" if D1, D2 and D3 are
>already derived from Base?

	The idea is you can treat all T* as Base*, or, 
you can single out D1, D2 and/or D3 for special treatment.

	select(t)
	type(Base* b){ b->print(); }
	type(D1* d1){ d1->D1Print(20); }

>
>>	Downcasting is not required by either of these mechanisms.
>>This mechanism should suffice in almost all cases where you 
>>think you need a heterogenous list.
>
>Heck, I've got a HOMOGENOUS list.  But to implement StudentList::get()
>I have to refer to my parent class (List::get()) which returns an
>Object *.  I have to convert it to StudentObj * and return it, 
>don't I.  

	Assuming you are using NIH, yes. Could you hassle
for a newer compiler?

>From what I understand you can ALWAYS do:
>
>	Object *pObj = pObjDerived;
>
>but you can't always do:
>
>	ObjDerived *pObjDerived = pObj;
>
>can you?  

	You can't ever do this, you require an explicit cast.
If the derivation is virtual, you cant do it at all.

>If you can, then why is there that silly
>::castdown() function in the NIH library doing for me?
>
>>	Downcasting does offer something neither the above 
>>mechanisms does, and for that reason I am suspicious of it.
>>It allows an arbitrarily chosen but finite set of classes
>>to be checked for, *as if* they had been declared
>>like a tagged pointer, at one local place in the program.
>>However at another place, another different set can be
>>chosen. Therefore, since the number of such places
>>in a program is unbounded, the number of derived classes
>>that are special is *UNBOUNDED*.
>
>I don't even follow what you are saying the advantage here
>is.  Could you please rephrase it?  I think it may have to
>do w/ not understanding what "tagged pointer" means (does it 
>refer to that wierd construct you used above?)

	The tagged pointers require you to list explicitly
the cases. So the T* above can be 'cast' as either
Base, D1, D2 or D3 pointer (or any base of these) but
no other class. But you can cast Object* to anything.

>
>>	Now polymorphism already manages an unbounded (arbitrary)
>>number of derived classes by homogenising the interfaces
>>(that is, by virtual functions). That such restrictions
>>are required to have polymorphism operate properly
>>in a system built of closed modules seems to indicate to
>>me that downcasting perverts the course of type safety.
>
>Nope.  I'm just trying to reuse an already written class (List)
>for my own purposes instead of reinventing the wheel, isn't that
>what the who point of Object-Oriented Programming was supposed
>to be?  

	Dont know. But reuse is surely important.

>The fact that I have to perform unwanted gyrations
>to make use of this supposedly generic container class may
>just indicate that the NIH library is garbage (an opinion that
>I already tend towards....) (if you wish to be generous, please
>read "poorly designed" where I have typed "garbage" :)

	No, it was probably well designed (I guess) for 
C++ version 1. C++ version 1 was severely restricted,
so really *it* was poorly designed. But it has been
upgraded so extensively that IMHO there is almost
no resemblance between ARM and version 1.

>
>>	I want to consider what happens in a system
>>with dynamic linkage. This can just be dynamic class loading,
>
>Another think I would be interested.  Loading a class from a
>file before you know what class is stored there is something I would
>very much like to be able to do.

	I do this in Windows, its easy. But it is not quite
what you think perhaps .. not like NIH. you must already
know that the class being loaded is derived from a particular
Base class, and you can only access it via the Base class interface.

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------