home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.lang.c++:11617 comp.std.c++:965
- Newsgroups: comp.lang.c++,comp.std.c++
- Path: 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: <1992Jul27.161441.7898@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: <9220719.894@mulga.cs.mu.OZ.AU>
- Date: Mon, 27 Jul 92 16:14:41 GMT
- Lines: 120
-
- > shang@corp.mot.com (David (Lujun) Shang) writes:
- >
- > >Now I give you an example that truely needs multiple dispatch.
- > >
- > >class Animal
- > >{ Animal * fight (Animal * a)
- > // simplified version for brevity
- > { return this->strength() > a->strength ? this : a; }
- > >};
- > >
- > >and we have the following fights:
- > >
- > >Animal * victor;
- > >..
- > >victor = wolf.fight (jackal);
- > >victor = lynx.fight (victor);
- > >victor = bull.fight (victor);
- > >..
- > >.....
-
- In article <9220719.894@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James
- HENDERSON) replies:
-
- > I don't quite understand you example.
- > It seems to be incomplete.
- > Presumeably after all the fights, you are going to do something like
- >
- > if (typeof(victor) == typeof(wolf))
- > cout << "The wolf won!\n";
- > else if (typeof(victor) == typeof(lynx))
- > cout << "The lynx won!\n";
- > else ...
- >
- > To me that looks like horrible design.
- > Why not just have
- >
- > cout << "The " << victor->name() << " won!\n";
- >
- > instead? Then there is no need for downcasting (and you also have a better
- > design!).
-
- Sorry that I did not complete my program, which caused confusion. I'm going to
- write something like:
-
- count << victor->name() << ", the " << type_name(typeof(*victor))
- << " won!\n";
-
- [note that from the animal name, you may not know what kind of the animal is]
- the result may be:
-
- Pooh, the bear won!
-
- or, I may write:
-
- bestow_on (victor).
-
- where bestow_on is a function which gives a female peer to the victor (suppose
- only the male can fight):
-
- void bestow_on (Animal * victor)
- { Animal * f = new typeof(*victor)(female));
- // suppose we need do some work for the female here
- // ...
- victor->mate(f); // type inference here ensure that f is the
- // correct type and the downcast is safe
- };
-
- here both RTTI and downcast are needed, though I did not write an explicit
- downcast which is actually happen in the call of "mate":
-
- victor->mate( (typeof(victor)) f);
-
- since the interface of mate specifies the input of animal must be the same type
- of animal as the victor [see my previous poster]:
-
- void Animal::mate (thisclass *);
-
- The downcast is performed implicitly and checked by the compiler to ensure each
- downcast is CORRECT and SAFE at run time. For example, if write:
-
- Animal * f = new bear;
- dog->mate(f);
-
- The compiler won't let you pass the above program because when you call
- dog->mate(f), f is the type of bear. The (implicit) downcast cannot be
- performed. The compiler won't let you pass either if it cannot infer whether it
- is the correct type, in this case, the programmer must present an explicit
- run-time type check to ensuure the correct downcast:
-
- if (typeof(*f)==Dog) dog->mate(f);
-
- However, if you write an explicit downcast here:
-
- dog->mate((Dog*) f);
-
- that means you are deliberately to break the type system. The compiler will
- give you a warning when it either knows the downcast is not correct or does not
- know whether it is correct.
-
- I wonder if you can figure out a better design that needs not RTTI and downcast
- for "bestow_on" and "mate". Downcast may not needed if you provide your own
- virtual function for the type id, say "Species()" as suggested by John. But I
- don't think it is a better design because it is not safe for the first two of
- following three reasons and not efficeint for the last reason:
-
- (1) You must remember to override the virtual function. If you forget, errors
- happen. The compiler has no way the essure a correct type id distribution.
-
- (2) You must remember to run-time check of the type id. The compiler has no way
- to help you to enssure the correct match. If you forget to check, you produce
- the error.
-
- (3) You let down the run time performance since you have much work of type
- checking that can be done at compile time done at run time.
-
- Downcast is not safe only when the compiler can not ensure that the downcast
- will not produce a cast between two different types. With language supported
- RTTI, all language supported automatic downcast will be deadly safe.
-
- David Shang
-