caw@munnari.oz.au (Chris Wright) (03/04/91)
I've been doing some tinkering in THINK C, in particular trying to work
out the binding strategy. I enclose some code which shows some interesting
aspects of the systems behaviour. It seems to perform dynamic binding
for some function calls, but exhibits static behaviour on other occasions.
Any comments?
chris
/*
The point of these classes is that the function trickyFnSuper() in the
superclass calls classFn (which has a definition both in the subclass
and in the superclass). From the behavior, it would appear that the
there is RUNTIME binding of the correct classFn(). I think this is what
the "virtual" keyword in C++ accomplishes.
More interesting, however, is the behaviour of the myToBeCast variable.
This starts out in life as a member of MySuperClass, but then gets
assigned to new(MySubClass). When the myToBeCast -> trickyFnSuper()
is evaluated, there is still the correct "runtime" binding to the
subclasses' ClassFn.
However, if we try to compile myToBeCast->uniqueToSubFn(), the
compiler chokes. I guess this is because we are looking a COMPILE time
behaviour, and not RUNTIME behaviour.
The compiler thinks that myToBeCast is a member of the
superclass for the purposes of method compilation. If
you cast myToBeCast : (MySubClass *) myToBeCast -> uniqueToSubFn()
then all is sweetness and light.
How come the compiler is smart enough to allow runtime (or dynamic)
binding to the subclasses methods, but not smart enough to
know that myToBeCast is now a member
of the subclass??????
*/
#include <stdio.h>
#include <oops.h>
struct MySuperClass : indirect {
MySuperClass *classInit(void);
int classInt;
int classFn(int);
int trickyFnSuper(int);
};
struct MySubClass : MySuperClass {
int classFn(int);
int uniqueToSubFn(int);
};
int MySuperClass::classFn(i)
int i;
{
return i + 1;
}
MySuperClass *MySuperClass::classInit(void)
{
classInt = 2;
return this;
}
int MySuperClass::trickyFnSuper(i)
int i;
{
int j;
j = classFn(i);
return j;
}
int MySubClass::classFn(i)
int i;
{
return i + 10;
}
int MySubClass::uniqueToSubFn(i)
int i;
{
return i + 100;
}
MySuperClass *mySuperInstance;
MySuperClass *myToBeCast;
MySubClass *mySubInstance;
main()
{
mySuperInstance = new(MySuperClass) ;
myToBeCast = new(MySubClass);
mySubInstance = new(MySubClass);
mySuperInstance -> classInit();
printf("%d\n", mySuperInstance->classFn(3)); /* ->4 */
printf("%d\n", mySuperInstance->classInt); /* ->2 */
printf("%d\n", mySuperInstance->trickyFnSuper(1)); /* ->2 */
printf("%d\n", mySubInstance->trickyFnSuper(1)); /* ->11 */
printf("%d\n", myToBeCast->trickyFnSuper(1)); /* ->11 */
printf("%d\n", mySubInstance->uniqueToSubFn(1)); /* ->101 */
/* printf("%d\n", myToBeCast->uniqueToSubFn(1)); -----CHOKES----*/
printf("%d\n", ((MySubClass *) myToBeCast)->uniqueToSubFn(1)); /* ->101 */
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
chris wright - a guest on melbourne university
if the mail bounces, try caw@munmurra.cs.mu.oz.u Lawson.English@p88.f15.n300.z1.fidonet.org (Lawson English) (03/06/91)
Chris Wright writes in a message to All
you cast myToBeCast : (MySubClass *) myToBeCast -> uniqueToSubFn()
CW> then all is sweetness and light. How come the compiler is smart
CW> enough to allow runtime (or dynamic)
CW> binding to the subclasses methods, but not smart enough to know
CW> that myToBeCast is now a member of the subclass??????
Because it's not very smart? Seriously, do you know of any compiler that keeps
track of type-casting? IE, if you do a "(char*) myInt", do you expect the compiler
to remember that myInt was just used as (*char)?
If not (and I'd love to see the headaches that THAT would cause if you found
a compiler that would actually do it), why do you expect a compiler to remember
the typecast for an object? I suppose that it could be built-in, simply for
objects, but that sounds like pretty un-documentable behavior to me...
Lawson
--
Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!300!15.88!Lawson.English
Internet: Lawson.English@p88.f15.n300.z1.fidonet.org