home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
- From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
- Subject: Re: Object metamorphosis - can/should it be done?
- Message-ID: <9223115.11413@mulga.cs.mu.OZ.AU>
- Sender: news@cs.mu.OZ.AU
- Organization: Computer Science, University of Melbourne, Australia
- References: <1992Aug17.223629.5722@fcom.cc.utah.edu>
- Date: Tue, 18 Aug 1992 05:43:36 GMT
- Lines: 111
-
- swillden@news.ccutah.edu (Shawn Willden) writes:
-
- >I ran across some interesting Objective-C code the other day and I
- >wondered if there is some way to implement it in C++. Then I wondered
- >if it was a good idea to try. Anyway, the concept is that an object
- >can be asked to mutate into an object of a different type. Under
- >Objective-C's concept of an object, any object can mutate to essentially
- >any other type because all messages are resolved at run-time. In C++'s
- >static system this is not possible, however, it seems to me that there
- >is at least one case in which it might be possible in C++ and maybe even
- >useful. Given a base class pointer or reference to a derived class
- >object, it should be possible to replace the derived class object with
- >an object of another derived type.
-
- One major problem with your example code
-
- >void Pupa::metamorphose() {
- > Pupa* old_me = this;
- > (Adult*)this = new Adult(*old_me);
- > delete old_me;
- >}
-
- is that "this" is passed by value, not by reference, so assignment to "this"
- is not going to have the desired effect.
-
- What you want is for Butterfly to contain a pointer to ButterflyStage.
- The Butterfly class should then be a 'smart reference' to that ButterflyStage.
- Each stage should have a metamorphosis() function that returns the next
- stage. The metamorphose() function will then reassign the pointer with a
- newly allocated stage pointer returned from metamorphosis().
-
- Here's how to do it in standard C++:
-
- class ButterflyStage {
- //...
- public:
- ButterflyStage() {...}
- ButterflyStage(Butterfly& b) {...}
- virtual void report()=0;
- virtual int can_fly()=0;
- //...
-
- virtual ButterflyStage* metamorphosis()=0;
- };
-
- class Pupa : public Butterfly {
- public:
- Pupa() { }
- void report() { cout << "I'm a caterpillar\n"; }
- int can_fly() { return 0; }
- ButterflyStage* metamorphosis() { return new Adult; }
- };
-
- class Adult : public Butterfly {
- public:
- Adult() { }
- void report() { cout << "I'm a real butterfly\n"; }
- int can_fly() { return 1; }
- ButterflyStage* metamorphosis() { return new Adult; }
- // maybe we should "return new Corpse" here :-)
- };
-
- class Butterfly {
- ButterflyStage *stage;
- public:
- Butterfly(ButterflyStage *s) : stage(s) {}
- // NB stage must be allocated with new!
- Butterfly() : stage(new Pupa) {} // optional default
- ~Butterfly() { delete stage; }
- Butterfly(const Butterfly& b) {...}
-
- void metamorphose() {
- ButterflyStage* next = stage->metamorphosis();
- delete stage;
- stage = next;
- }
-
- // you have to write forwarding functions for every function
- // in class ButterflyStage ...
- void report() { stage->report(); }
- int can_fly() { return stage->can_fly(); }
- // ...
- };
-
- main() {
- Butterfly fred(new Pupa);
- fred.report();
- fred.metamorphose();
- fred.report();
- }
-
- This gives you the desired output:
-
- >I'm a caterpillar
- >I'm a real butterfly
-
- Aside: this is another example where we want to do smart references.
- A Butterfly is a smart reference to a ButterflyStage.
- I could post code to show how to do it using overloading of operator
- dot as per Jim Adcock's proposal, but since I am probably the ONLY
- person in possession of a compiler that implements his proposal (I have
- modified gcc 2.2.2 to do this) there isn't much point.
-
- >Shawn Willden
- >swillden@icarus.weber.edu
-
- --
- Fergus Henderson fjh@munta.cs.mu.OZ.AU
- This .signature VIRUS is a self-referential statement that is true - but
- you will only be able to consistently believe it if you copy it to your own
- .signature file!
-