home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / cplus / 12481 < prev    next >
Encoding:
Text File  |  1992-08-17  |  3.9 KB  |  123 lines

  1. Newsgroups: comp.lang.c++
  2. Path: sparky!uunet!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
  3. From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
  4. Subject: Re: Object metamorphosis - can/should it be done?
  5. Message-ID: <9223115.11413@mulga.cs.mu.OZ.AU>
  6. Sender: news@cs.mu.OZ.AU
  7. Organization: Computer Science, University of Melbourne, Australia
  8. References: <1992Aug17.223629.5722@fcom.cc.utah.edu>
  9. Date: Tue, 18 Aug 1992 05:43:36 GMT
  10. Lines: 111
  11.  
  12. swillden@news.ccutah.edu (Shawn Willden) writes:
  13.  
  14. >I ran across some interesting Objective-C code the other day and I 
  15. >wondered if there is some way to implement it in C++.  Then I wondered
  16. >if it was a good idea to try.  Anyway, the concept is that an object
  17. >can be asked to mutate into an object of a different type.  Under
  18. >Objective-C's concept of an object, any object can mutate to essentially
  19. >any other type because all messages are resolved at run-time.  In C++'s
  20. >static system this is not possible, however, it seems to me that there 
  21. >is at least one case in which it might be possible in C++ and maybe even 
  22. >useful.  Given a base class pointer or reference to a derived class
  23. >object, it should be possible to replace the derived class object with
  24. >an object of another derived type.  
  25.  
  26. One major problem with your example code
  27.  
  28. >void Pupa::metamorphose() {
  29. >    Pupa* old_me = this;
  30. >    (Adult*)this = new Adult(*old_me);
  31. >    delete old_me;
  32. >}
  33.  
  34. is that "this" is passed by value, not by reference, so assignment to "this"
  35. is not going to have the desired effect.
  36.  
  37. What you want is for Butterfly to contain a pointer to ButterflyStage.
  38. The Butterfly class should then be a 'smart reference' to that ButterflyStage.
  39. Each stage should have a metamorphosis() function that returns the next
  40. stage. The metamorphose() function will then reassign the pointer with a
  41. newly allocated stage pointer returned from metamorphosis().
  42.  
  43. Here's how to do it in standard C++:
  44.  
  45. class ButterflyStage {
  46.     //...
  47. public:
  48.     ButterflyStage()        {...}
  49.     ButterflyStage(Butterfly& b)    {...}
  50.     virtual void report()=0;
  51.     virtual int  can_fly()=0;
  52.     //...
  53.  
  54.     virtual ButterflyStage* metamorphosis()=0;
  55. };
  56.  
  57. class Pupa : public Butterfly {
  58. public:
  59.     Pupa()            { }
  60.     void report()        { cout << "I'm a caterpillar\n"; }
  61.     int  can_fly()        { return 0; }
  62.     ButterflyStage* metamorphosis() { return new Adult; }
  63. };
  64.  
  65. class Adult : public Butterfly {
  66. public:
  67.     Adult()            { }
  68.     void report()        { cout << "I'm a real butterfly\n"; }
  69.     int  can_fly()        { return 1; }
  70.     ButterflyStage* metamorphosis() { return new Adult; }
  71.                 // maybe we should "return new Corpse" here :-)
  72. };
  73.  
  74. class Butterfly {
  75.     ButterflyStage *stage;
  76. public:
  77.     Butterfly(ButterflyStage *s) : stage(s) {}
  78.         // NB stage must be allocated with new!
  79.     Butterfly() : stage(new Pupa) {}        // optional default
  80.     ~Butterfly() { delete stage; }
  81.     Butterfly(const Butterfly& b) {...}
  82.  
  83.     void metamorphose() {
  84.         ButterflyStage* next = stage->metamorphosis();
  85.         delete stage;
  86.         stage = next;
  87.     }
  88.  
  89.     // you have to write forwarding functions for every function
  90.     // in class ButterflyStage ... 
  91.     void report() { stage->report(); }
  92.     int can_fly() { return stage->can_fly(); }
  93.     // ...
  94. };
  95.  
  96. main() {
  97.     Butterfly fred(new Pupa);
  98.     fred.report();
  99.     fred.metamorphose();
  100.     fred.report();
  101. }
  102.  
  103. This gives you the desired output:
  104.  
  105. >I'm a caterpillar
  106. >I'm a real butterfly
  107.  
  108. Aside: this is another example where we want to do smart references.
  109. A Butterfly is a smart reference to a ButterflyStage.
  110. I could post code to show how to do it using overloading of operator
  111. dot as per Jim Adcock's proposal, but since I am probably the ONLY
  112. person in possession of a compiler that implements his proposal (I have
  113. modified gcc 2.2.2 to do this) there isn't much point.
  114.  
  115. >Shawn Willden
  116. >swillden@icarus.weber.edu    
  117.  
  118. -- 
  119. Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
  120. This .signature VIRUS is a self-referential statement that is true - but 
  121. you will only be able to consistently believe it if you copy it to your own
  122. .signature file!
  123.