[comp.std.c++] Address of member function

delft@fwi.uva.nl (Andre van Delft) (10/28/90)

A few days ago I had a question on comp.lang.c++ about taking the address
of a member function:

>>For a call-back mechanism, I want to store the address of a non-static
>>class member function. Turbo-C++ does not allow this ("member function
>>pointers are not true pointer types, and do not refer to any particular
>>instance of a class"). 
>>
>>What does ANSI-C++ say about this? Are C++ implementations free to 
>>decide whether addresses of member functions are normal addresses?
>>If so, what do other C++ implementations decide? 

("ANSI-C++" should have been "AT&T C++, 2.0", of course.) Thanks those
who responded. However, my question was not well understood by some,
e.g.,

>It doesn't make sense to call a class member function without an instance of
>that class.  It *should* be illegal.

I meant the following: why is it allowed to take the address of:

a GLOBAL VARIABLE
a GLOBAL FUNCTION 
a MEMBER VARIABLE, i.e. a variable local to an instance of a class

but why is it NOT allowed to take the address of

a MEMBER FUNCTION, i.e. a function local to an instance of a class

Example:


int i;
int f(int k) {printf("%d\n",i+k);}

class c {
  public:
    int j;
    int g(int k) {printf("%d\n",j+k);}
}

main() {
  int*ip,*jp;
  int(*fp)(int);
  int(*gp)(int);
  c anObject;

  ip  = &         i;        // OK
  jp  = &anObject.j;        // OK
  fp  = &         f;        // OK
  gp  = &anObject.g;        // NOT OK
  *ip = 1;
  *jp = 2;
  fp(3);                     // prints 4
  gp(4);                     // would print 6, if not NOT OK ...
}

I want the address of g() as belonging to anObject, and this address should
have the same size of any address. Current C++ implementations do not allow
this: it is reasonable that any instance of a class has its own space for its
instance variables, but it would be inefficient when it also had the complete
code for its member functions for itself. Instead, most C++ versions implement a
member function as a global function with an extra parameter that points tothe
object to which the message is directed. Something like:

                  int cg(c*,int)    for   c::g
with actual use   cg(&anObject,5)   for   anObject.g(5)).

However, it would not be too inefficient to put part of the member function
code in the space of each instance: in 'anObject', this "present" 'g' function

would just call 'cg' with 'this' as extra parameter: 'cg(this,5)'. With a new
"access modifier" programmers could force such present functions, so that
taking their address would be legal, without overhead for nonpresent functions:

class c {
  public:
    int j;
    present int g(int k) {printf("%d\n",j+k);}
}


Andre van Delft
DELFT@fwi.uva.nl

delft@fwi.uva.nl (Andre van Delft) (10/29/90)

steve@taumet.com (Steve Clamage) writes:

> >delft@fwi.uva.nl (Andre van Delft) writes:
>
> >I meant the following: why is it allowed to take the address of:
>
> >a GLOBAL VARIABLE
> >a GLOBAL FUNCTION
> >a MEMBER VARIABLE, i.e. a variable local to an instance of a class
>
> >but why is it NOT allowed to take the address of
>
> >a [nonstatic] MEMBER FUNCTION, i.e. a function local to an instance of a
class
>
>The problem comes with virtual functions.  Suppose that you could take
>the address of a virtual member function.  You would still have to call
>it in conjuction with some object (so "this" could refer to something).
>Suppose we had something like
>        class C { ... public: virtual f(); g();... };
>        class D : public C { ... public: virtual f(); ... };
>        D d;
>
>        void (*fp)() = c.f;     // presently illegal
>        C* cp = &d;
>
>1.      cp->f();        // virtual call, in this case calls dp->D::f()
>2.      cp->fp();       // invented sytax -- what do we do here?
>3.      fp();           // ok if fp had the address of an ordinary function

I would *never* propose the "invented syntax" cp->fp() since fp is a name of
a global variable instead of a name of a member in class C.
I do not see why virtual functions would be a problem for my proposal:
a new "access modifier", e.g., 'present', for member functions so that you
can take their addresses (which you can also do with member variables), as in

class C {present void f(void);}
...
C anObject;
void (*fp)(void);
...
fp = anObject.f;
...
fp();

The preprocessor/compiler would

1. place in *each* instance 'anObject' of a class C, and for each of its
'present'
   functions 'f(parms)'  simple code that calls the code C::f(&anObject,parms)
   (which is shared among all objects of the class for space efficiency). 

2. transform a call to a 'present' function f(parms) in anObject into
   something like ( (void(*)(parms) (&anObject.f) ) (parms) instead of
   something like C::f(anObject,parms)

No problem with virtual functions: each object instance will know itself to
what class it belongs, and implement the 'present' function accordingly.

Andre van Delft
DELFT@fwi.uva.nl