From: sumani@cs.tamu.edu (Suman K Inala)
Newsgroups: comp.lang.c++
Subject: Query: object interactions
Date: 23 Nov 1992 18:13:32 GMT
Organization: Texas A&M University, College Station
NNTP-Posting-Host: photon.tamu.edu
Summary: non-existent member functions & more
Keywords: objects interactions

I am having problems trying to implement objects which can interact
with each other in a wide variety of ways.  Basically, I would
like for one object to be able to call any method for any arbitrary
object, even if that method doesn't exist (in which case it does
nothing) without having to have a base class with a thousand
virtual functions.

First, let me try to explain it in code:

#include <iostream.h>

class X {
	char x;
public:
	X() { x = 'x'; }
	void xvalue(void) { cout << x; }  // xvalue() always says 'x'
};

class Y {
	char y;
public:
	Y() { y = 'y'; }
	void yvalue(void) { cout << y; } // yvalue() always says 'y'
};

int main(void) {
	X x;
	Y y;
	void *ptr = &x;                 // ptr to object x of class X

	cout << "-----------\n";

	x.xvalue();     // says 'x'
	y.yvalue();     // says 'y'
//	y->xvalue();	//  Compile error--as it should
//	x->yvalue();	//  Compile error--as it should

	((X *) ptr)->xvalue();  // Prints 'x' as it should
	((Y *) ptr)->yvalue();  // Prints x!  Not what I want...
	                        // Though I understand why it does this
			        // This is asking for a crash

				// What I would like for it to do instead
				// is nothing, since ptr doesn't have
				// the member function xvalue(); or better
				// yet, to call some default function

/* 
I could do a virtual function, cast or declare ptr
to be of the base class, and call the value() but
that is not what I want to do.  I have to be able
to handle class Z which does not have a the virtual function value()
To have all objects of class Object is acceptable
but they can't have all the same member functions...
Otherwise I end up with just an atrocious amount of
virtual functions in the base class
*/
	return 0;
}

Let me try to explain in plain words.  Say we have an object key.
When we use the key, we select one of many possible objects to use
it on, like for instance, a door, a bear, a feather, etc.  These
objects are mostly very different, but any of them can be selected.
We want to call (*if it exists*) the member function unlock() of
the selected object.  If the member function does not exist, have
it do nothing or perhaps say 'Nothing happens.'

One solution would be to derive all of these objects from the
same base class and define a virtual function for each of the verbs for
all possible objects which could be used.  However, if we have
1000 objects each with its own verb (a key can unlock, a hammer can
hit, a knife can slice, a furnace can heat, a pencil can mark,
a shredder can grind..) we end up having a base class with each of
these verbs as a virtual function... Surely there is a more elegant
solution.  We don't want class Bear to have a virtual function
unlock() do we?

(The C++ example would perhaps have been better if I had derived
X & Y from W, inheriting the member function value... And then
tried to call value from class Z, which perhaps has a common
ancestor with W, but does not have the member function value().)

Maybe one way to put this is - 
if for ptr p there exists member function value()
	 p->value(); 
else 
	say 'Nothing happens.';

Some other questions: let's say we use the key on the door.  The
door will only unlock if the key is blue.  Is there any way
to determine automatically what object called it, or must the
this ptr for key be passed manually?  In addition, since not all
keys will have the getcolor() method, how would this work?  If
the member function does not exist, then the door object would
like to know that, and take the appropriate action (most likely
say 'I don't open for non-blue keys.')

I am using Borland C++ 3.1.  I am thinking of using the CLASSLIB
library supplied by them, which the next question is kind of
specific to.

Let us say that the key does have a getcolor() method, but
it returns 'red' instead.  I would like the door to cause the
key and everything attached to it to become glued to the door, being
unable to move, or perhaps become 20% heavier.  Would I have to
encode a 'naive physics' into each object which could interact
with the door?  Using the CLASSLIB library, can an object know what
object contains it (w/o me changing the original class?)  What
if the key is in a bag, and I say to a particular instantiation of key
moveto(chest);  can the key copy itself to the chest (of course)
and then delete itself from the bag in a safe manner?  It should
not simply delete the this ptr because the bag will not know 
that it has been deleted and will become confused.  How is this
done then?

Last question:  let's say I need to send some objects over some
line to another machine.  The objects to be send are within a
well-constrained set of classes, ie. each machine knows that
any object sent will only be a an object of class X, Y, or Z,
though with different attributes of course.  One way to do
it would be through a giant switch function, but that seems
arbitrary and not the OO way.  Each time a new class would
be added, changes would have to be made to the switch statement.
Would sending them via a stream be portable across machines?
What are the mechanics behind this?  (ie. a byte or word signifying
what class the object belongs to, and then the data members?

That's it; I'd really appreciate some help or comments why certain
things can or can not be done.

--
Till next time,                \o/   \o/
                                V \o/ V     email:pinky@tamu.edu
<>  Sam  Inala  <>                 V

--
Till next time,                \o/   \o/
                                V \o/ V     email:pinky@tamu.edu
<>  Sam  Inala  <>                 V

Newsgroups: comp.lang.c++