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