home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / cplus / 11617 < prev    next >
Encoding:
Internet Message Format  |  1992-07-27  |  4.7 KB

  1. Xref: sparky comp.lang.c++:11617 comp.std.c++:965
  2. Newsgroups: comp.lang.c++,comp.std.c++
  3. Path: sparky!uunet!ftpbox!motsrd!news
  4. From: shang@corp.mot.com (David (Lujun) Shang)
  5. Subject: Re: run-time type checking (was: Re: Covariant Types in Derived Classes)
  6. Message-ID: <1992Jul27.161441.7898@cadsun.corp.mot.com>
  7. Sender: news@cadsun.corp.mot.com
  8. Reply-To: shang@corp.mot.com
  9. Organization: Motorola, Inc., Software Research and Development, Rolling Meadows, IL. 60008
  10. References: <9220719.894@mulga.cs.mu.OZ.AU>
  11. Date: Mon, 27 Jul 92 16:14:41 GMT
  12. Lines: 120
  13.  
  14. > shang@corp.mot.com (David (Lujun) Shang) writes:
  15. > >Now I give you an example that truely needs multiple dispatch.
  16. > >
  17. > >class Animal
  18. > >{  Animal * fight (Animal * a)
  19. >     // simplified version for brevity
  20. >     {  return this->strength() > a->strength ? this : a; }
  21. > >};
  22. > >
  23. > >and we have the following fights:
  24. > >
  25. > >Animal * victor;
  26. > >..
  27. > >victor = wolf.fight (jackal);
  28. > >victor = lynx.fight (victor);
  29. > >victor = bull.fight (victor);
  30. > >..
  31. > >.....
  32.  
  33. In article <9220719.894@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James  
  34. HENDERSON) replies:
  35.  
  36. > I don't quite understand you example.
  37. > It seems to be incomplete.
  38. > Presumeably after all the fights, you are going to do something like
  39. >     if (typeof(victor) == typeof(wolf))
  40. >         cout << "The wolf won!\n";
  41. >     else if (typeof(victor) == typeof(lynx))
  42. >         cout << "The lynx won!\n";
  43. >     else ...
  44. > To me that looks like horrible design.
  45. > Why not just have
  46. >     cout << "The " << victor->name() << " won!\n"; 
  47. > instead? Then there is no need for downcasting (and you also have a better
  48. > design!).
  49.  
  50. Sorry that I did not complete my program, which caused confusion. I'm going to  
  51. write something like:
  52.  
  53.         count << victor->name() << ", the " << type_name(typeof(*victor))
  54.               << " won!\n";
  55.  
  56. [note that from the animal name, you may not know what kind of the animal is] 
  57. the result may be:
  58.  
  59.         Pooh, the bear won!
  60.  
  61. or, I may write:
  62.  
  63.         bestow_on (victor).
  64.  
  65. where bestow_on is a function which gives a female peer to the victor (suppose  
  66. only the male can fight):
  67.  
  68.        void bestow_on (Animal * victor)
  69.        {    Animal * f = new typeof(*victor)(female));
  70.             // suppose we need do some work for the female here
  71.             // ...
  72.             victor->mate(f); // type inference here ensure that f is the 
  73.                              // correct type and the downcast is safe
  74.        };
  75.  
  76. here both RTTI and downcast are needed, though I did not write an explicit  
  77. downcast which is actually happen in the call of "mate":
  78.  
  79.         victor->mate( (typeof(victor)) f);
  80.  
  81. since the interface of mate specifies the input of animal must be the same type  
  82. of animal as the victor [see my previous poster]:
  83.  
  84.        void Animal::mate (thisclass *);
  85.  
  86. The downcast is performed implicitly and checked by the compiler to ensure each  
  87. downcast is CORRECT and SAFE at run time. For example, if write:
  88.  
  89.        Animal * f = new bear;
  90.        dog->mate(f);
  91.  
  92. The compiler won't let you pass the above program because when you call  
  93. dog->mate(f), f is the type of bear. The (implicit) downcast cannot be  
  94. performed. The compiler won't let you pass either if it cannot infer whether it  
  95. is the correct type, in this case, the programmer must present an explicit  
  96. run-time type check to ensuure the correct downcast:
  97.  
  98.       if (typeof(*f)==Dog) dog->mate(f); 
  99.  
  100. However, if you write an explicit downcast here:
  101.  
  102.        dog->mate((Dog*) f);
  103.  
  104. that means you are deliberately to break the type system. The compiler will  
  105. give you a warning when it either knows the downcast is not correct or does not  
  106. know whether it is correct.
  107.  
  108. I wonder if you can figure out a better design that needs not RTTI and downcast  
  109. for "bestow_on" and "mate". Downcast may not needed if you provide your own  
  110. virtual function for the type id, say "Species()" as suggested by John. But I  
  111. don't think it is a better design because it is not safe for the first two of  
  112. following three reasons and not efficeint for the last reason:
  113.  
  114. (1) You must remember to override the virtual function. If you forget, errors  
  115. happen. The compiler has no way the essure a correct type id distribution.
  116.  
  117. (2) You must remember to run-time check of the type id. The compiler has no way  
  118. to help you to enssure the correct match. If you forget to check, you produce  
  119. the error.
  120.  
  121. (3) You let down the run time performance since you have much work of type  
  122. checking that can be done at compile time done at run time.
  123.  
  124. Downcast is not safe only when the compiler can not ensure that the downcast  
  125. will not produce a cast between two different types. With language supported  
  126. RTTI, all language supported automatic downcast will be deadly safe.
  127.  
  128. David Shang
  129.