Article View: comp.std.c++
Article #47Re: run-time type checking (was: Re: Covariant Types in Derived Classes)
From: David (Lujun) Shang
Date: Fri, 31 Jul 1992 23:01
Date: Fri, 31 Jul 1992 23:01
109 lines
5270 bytes
5270 bytes
In article <1992Jul30.172830.18501@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU
(John MAX Skaller) writes:
> I refered to compiler generated RTTI. User generated RTTI
> must obey the current restrictions of C++, and so is as sound and safe
> as C++ currently is. I also refered to a specific case in one place,
> and say in general in another, intending to say 'always'. OK?
>
I cannot understand why user generated RTTI is sound and safe while the
compiler generated RTTI is not.
> >
> >> Actually, I think downcasting is OK when you already knew what the
> >> type was, or could have. Then it is just a convenience. And safe.
> >>
> >Then we have not disagreement any more.
>
> Well, I'm not sure about that. We certainly dont have a
> specific *agreement* about when downcasting is sound and when
> it is not, nor how to suitably constrain it.
>
If you think "downcasting is OK when you already knew what the type is", then
we have no disagreement. I said from the begining that the downcast should only
be allowed when you already know that the cast is on the exact type you want.
How do you know within a polymorphic behavior? Just by explicit run time type
check. The compiler will *enforce* you to do so in order to produce the safe
code. If you perform a downcast which you are not sure of the type within the
context, the compiler does not know either, then the compiler will not let your
program pass.
> I am looking at a constraint where all the things that
> a function can downcast to must be listed (or implied by the list)
> in the interface.
>
> f(Base[Derived1,Derived2]*);
>
> This mechanism has some nice features, although I am
> not sure about its soundness yet.
>
Are Derived1 and Derived2 sealed classes? Or is it true that the pointer
"Base[Derived1,Derived2]*" can only accept exactly two derived classes ( no
derived classes of Derived1 or Derived2)? IF NOT, such constraint helps nothing
in RTTI and downcast. Let me suppose YES, it still helps little (see below)
> Member functions can always downcast to their class.
> That immediately implies a 'thisclass' facility, and with no
> additional syntax in the declaration.
>
It is never a necissity to downcast "this" to its own class! "thisclass" is not
used to specify "this", it's a kind of garbage to say that "this cat is a cat".
"thisclass" is used to specify other object (input of the member function) that
is of the same type of this object. Member function CANNOT downcast its input
to its class without care if the input is not specified by "thisclass".
> Furthermore, explicit downcasting operators are not
> required always, since the declaration already lists the legal
> downcasts.
>
True, but not by your reason. Example,
Animal a1 = new Cat;
Animal a2 = new Dog;
Cat c = *a1;
Dog *d = a2;
No explicit RTTC required here. Both you and the complier know these downcasts
are correct and safe;
You proposed a constraint through a fixed set of *exact* types (I suppose so).
What is the purpose of such contraint? It cannot eliminates or even reducing
the necessity of run time type check. Non-derterminisim between the two and
among the infinitive both require run time type check.
When I refer to a fixed set of "exact types", I usually use them to make the
interface more precise. But additional RTTC is needed when you pass a less
constrained argument to this interface.
> Even better, the syntax might support casting to unrelated
> types, and can be implemented then, and when no virtual functions
> are available, by using tagged pointers or some other mechanism.
>
A complete RTTI should already support casting from a set of unrealted types to
a concrete type. It has nothing to do with any constraint.
> Finally, for the moment, one can implement
>
> f(Base[Derived1, Derived2]* b)
> {
> ...
> type switch(ab) {
> case Derived1:
> b->Derived1_member();
> case Derived2:
> b->Derived2_member();
> default:
> b->Base_member();
> };
> }
>
> although there would have to be an implied break after each case.
No default case needed here in the type switch because the interface of "f"
already tells you that there are only two cases of the input type. This is the
reason we need constraint: to help the resulting implementation more correct.
While "thiscalss" describes a covariant constraint of dependent types, tagged
union types (what you proposed is actually a kind of tagged union type as far
as I can understand) desribes a constraint of independent types. They cannot be
replaced with each other.
David Shang
Technical Details
Message-ID:
<1992Jul31.230135.1201@cadsun.corp.mot.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!ftpbox!motsrd!newsReferences:
<1992Jul30.172830.18501@ucc.su.OZ.AU>Show Full Headers
Complete Article Headers
Newsgroups: comp.std.c++,comp.lang.c++ Path: arc1-ca.pugleaf.net!sparky!uunet!ftpbox!motsrd!news From: shang@corp.mot.com (David (Lujun) Shang) Subject: Re: run-time type checking (was: Re: Covariant Types in Derived Classes) Message-ID: <1992Jul31.230135.1201@cadsun.corp.mot.com> Sender: news@cadsun.corp.mot.com Reply-To: shang@corp.mot.com Organization: Motorola, Inc., Software Research and Development, Rolling Meadows, IL. 60008 References: <1992Jul30.172830.18501@ucc.su.OZ.AU> Date: Fri, 31 Jul 92 23:01:35 GMT Lines: 112