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

  1. Newsgroups: comp.lang.c++
  2. Path: sparky!uunet!caen!hellgate.utah.edu!fcom.cc.utah.edu!swillden
  3. From: swillden@news.ccutah.edu (Shawn Willden)
  4. Subject: Object metamorphosis - can/should it be done?
  5. Message-ID: <1992Aug17.223629.5722@fcom.cc.utah.edu>
  6. Sender: news@fcom.cc.utah.edu
  7. Organization: University of Utah Computer Center
  8. X-Newsreader: Tin 1.1 PL3
  9. Date: Mon, 17 Aug 92 22:36:29 GMT
  10. Lines: 101
  11.  
  12. I ran across some interesting Objective-C code the other day and I 
  13. wondered if there is some way to implement it in C++.  Then I wondered
  14. if it was a good idea to try.  Anyway, the concept is that an object
  15. can be asked to mutate into an object of a different type.  Under
  16. Objective-C's concept of an object, any object can mutate to essentially
  17. any other type because all messages are resolved at run-time.  In C++'s
  18. static system this is not possible, however, it seems to me that there 
  19. is at least one case in which it might be possible in C++ and maybe even 
  20. useful.  Given a base class pointer or reference to a derived class
  21. object, it should be possible to replace the derived class object with
  22. an object of another derived type.  Something like:
  23.  
  24. class Butterfly
  25.     {
  26.     // some data here.
  27.     public:
  28.     Butterfly()            {...}
  29.     Butterfly(Butterfly& b)        {...}
  30.     // The metamorphose() function will turn an object of some
  31.     // descendant type into an object of some other descendant 
  32.     // type.
  33.     virtual void metamorphose() = 0;
  34.     virtual void report()        {cout << "I'm a generic butterfly\n";}
  35.     };
  36.  
  37. class Pupa : public Butterfly
  38.     {
  39.     // Note that this method is private.  This is to insure that
  40.     // it is *only* called through the base class interface. 
  41.     void metamorphose();
  42.     public:
  43.     Pupa()            {...}
  44.     void report()        {cout << "I'm a caterpillar\n";}
  45.     };
  46.  
  47. class Adult : public Butterfly
  48.     {
  49.     // Again, this method is private.
  50.     void metamorphose();
  51.     public:
  52.     Adult()                    {...}
  53.     Adult(Butterfly& b) : Butterfly(b)    {...}
  54.     void report()        {cout << "I'm a real butterfly\n";}
  55.     };
  56.  
  57. void Pupa::metamorphose()
  58.     {
  59.     Pupa* old_me = this;
  60.     (Adult*)this = new Adult(*old_me);
  61.     delete old_me;
  62.     }
  63.  
  64. main()
  65.     {
  66.     Butterfly *fred = new Pupa;
  67.  
  68.     fred->report();
  69.     fred->metamorphose();
  70.     fred->report();
  71.     }
  72.  
  73. with the desired output being, of course:
  74. I'm a caterpillar
  75. I'm a real butterfly
  76.  
  77. Obviously there are a few holes in my example (like what if the Pupa being
  78. asked to metamorphose was automatically allocated and I delete it).  GCC
  79. won't let me actually DO this (it complains heartily about any assignments
  80. to this) and while it let me compile something like this:
  81.  
  82. void Pupa::change(void*& p)
  83.     {
  84.     p = (void*)new Adult((Pupa*)p);
  85.     }
  86.  
  87. void Pupa::metamorphose()
  88.     {
  89.     Pupa* old_me = this;
  90.     change((void*)this);
  91.     delete old_me;
  92.     }    
  93.  
  94. the output was:
  95. I'm a caterpillar
  96. I'm a caterpillar
  97.  
  98. I haven't bothered compiling to assembly to figure out exactly why it doesn't
  99. do what I want it to, but it's clear that it doesn't.
  100.  
  101. So, some questions:
  102.     1)    Is there any way to make this work (portably or unportably).
  103.     2)    Why is this a bad idea?  Or is it?
  104.     3)    Suppose I REALLY wanted to do this.  Are there better ways 
  105.         that don't require me to play tricks with the type system?
  106.         One way to get the same effect (the one that comes to my mind
  107.         first) is to make a class Butterfly that contains a `state'
  108.         variable that is changed by the metamorphose() method and
  109.         switched on by report() and its ilk.  Any other suggestions?
  110.     
  111. Shawn Willden
  112. swillden@icarus.weber.edu    
  113.