Topic: Address of member function
Author: delft@fwi.uva.nl (Andre van Delft)
Date: 27 Oct 90 20:16:28 GMT Raw View
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 to the
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
Author: delft@fwi.uva.nl (Andre van Delft)
Date: 29 Oct 90 00:01:51 GMT Raw View
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