home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!caen!hellgate.utah.edu!fcom.cc.utah.edu!swillden
- From: swillden@news.ccutah.edu (Shawn Willden)
- Subject: Object metamorphosis - can/should it be done?
- Message-ID: <1992Aug17.223629.5722@fcom.cc.utah.edu>
- Sender: news@fcom.cc.utah.edu
- Organization: University of Utah Computer Center
- X-Newsreader: Tin 1.1 PL3
- Date: Mon, 17 Aug 92 22:36:29 GMT
- Lines: 101
-
- 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. Something like:
-
- class Butterfly
- {
- // some data here.
- public:
- Butterfly() {...}
- Butterfly(Butterfly& b) {...}
- // The metamorphose() function will turn an object of some
- // descendant type into an object of some other descendant
- // type.
- virtual void metamorphose() = 0;
- virtual void report() {cout << "I'm a generic butterfly\n";}
- };
-
- class Pupa : public Butterfly
- {
- // Note that this method is private. This is to insure that
- // it is *only* called through the base class interface.
- void metamorphose();
- public:
- Pupa() {...}
- void report() {cout << "I'm a caterpillar\n";}
- };
-
- class Adult : public Butterfly
- {
- // Again, this method is private.
- void metamorphose();
- public:
- Adult() {...}
- Adult(Butterfly& b) : Butterfly(b) {...}
- void report() {cout << "I'm a real butterfly\n";}
- };
-
- void Pupa::metamorphose()
- {
- Pupa* old_me = this;
- (Adult*)this = new Adult(*old_me);
- delete old_me;
- }
-
- main()
- {
- Butterfly *fred = new Pupa;
-
- fred->report();
- fred->metamorphose();
- fred->report();
- }
-
- with the desired output being, of course:
- I'm a caterpillar
- I'm a real butterfly
-
- Obviously there are a few holes in my example (like what if the Pupa being
- asked to metamorphose was automatically allocated and I delete it). GCC
- won't let me actually DO this (it complains heartily about any assignments
- to this) and while it let me compile something like this:
-
- void Pupa::change(void*& p)
- {
- p = (void*)new Adult((Pupa*)p);
- }
-
- void Pupa::metamorphose()
- {
- Pupa* old_me = this;
- change((void*)this);
- delete old_me;
- }
-
- the output was:
- I'm a caterpillar
- I'm a caterpillar
-
- I haven't bothered compiling to assembly to figure out exactly why it doesn't
- do what I want it to, but it's clear that it doesn't.
-
- So, some questions:
- 1) Is there any way to make this work (portably or unportably).
- 2) Why is this a bad idea? Or is it?
- 3) Suppose I REALLY wanted to do this. Are there better ways
- that don't require me to play tricks with the type system?
- One way to get the same effect (the one that comes to my mind
- first) is to make a class Butterfly that contains a `state'
- variable that is changed by the metamorphose() method and
- switched on by report() and its ilk. Any other suggestions?
-
- Shawn Willden
- swillden@icarus.weber.edu
-