gbaciu@watcgl.waterloo.edu (George Baciu [CGL]) (03/26/90)
I would like to know if the following can be considered a dependable feature or a C++ compliler implementation dependent problem. Consider calling a member function through a pointer whose type is NOT pointer-to-class-member-function returning type T but, to a "global" function returning type T - all arguments being of equal type. It seems to me that cfront 2.0: 1. does not complain if the appropriate type casting is done; 2. at run time, the argument list is screwed up by an implicit insertion of "this" pointer, in front of the list of arguments. This can cause problems if it is C++ implementation dependent. However, if ALL C++ compilers are to behave in the same manner, then it can be used as a feature in the cases where the class name for the function being called is not known in advance, but the function return type and arguments are known. Here is an example: ----------------------------- cut here ------------------------------ // Test for passing arguments through calling a member function through // a pointer to function in another class. // NOTE: pointer "this" is passed implicitly, so it screws up the // argument list. In order to get around it, the function pointer type // must have as first argument a void pointer and, when it is invoked, // "this" must be the first argument to be passed through. // FEATURE or BUG?? //----------------------------------------------------------------------- // output follows: // f = 654 fp = 654 // f = 630 fp = 630 // &d = 2147475332 // b = 2147475336 // D:i=99 // B:i=999 // n = 23552 // b = 23556 // D:i=88 // B:i=888 //----------------------------------------------------------------------- #include <stdio.h> #include <stream.h> // NOTE the extra argument "const void* p" which must be defined // so as to take care of the implicit "this" pointer, when the // function is called through a pointer to function of type PFC typedef void (*PFC)(const void* p, int i); class C { public: PFC fp; C(PFC f) : fp(f) { cout << "f = " << (int) f << " fp = " << (int) fp << "\n"; } ~C() {} }; class B { static C S; public: B() { } ~B() { } // NOTE: when printn(i) is called through S.fp, "this" // is passed implicitly. So, printn does not need an // argument to account for "this". void printn(int i) { printf("B:i=%d\n",i); } void runfp(int i) { S.fp(this,i); } }; class D : public virtual B { static C S; public: D() { } ~D() { } void printn(int i) { printf("D:i=%d\n",i); } void runfp(int i) { S.fp(this,i); } }; // Function pointers of functions in classes B and D, respectively, // assigned to fp pointer of class C. C B::S((PFC) &B::printn); C D::S((PFC) &D::printn); main () { D d; D* n = new D; B* b = &d; // this will point to members of d. printf("&d = %d\n", (int) &d); printf(" b = %d\n", (int) b); d.runfp(99); b->runfp(999); b = n; printf(" n = %d\n", (int) n); printf(" b = %d\n", (int) b); n->runfp(88); b->runfp(888); } ----------------------------- cut here ------------------------------ -- George Baciu ------------------------------------------------- | GBaciu@watcgl.Waterloo.edu GBaciu@watcgl.UWaterloo.CA | | * Computer Graphics Lab * | | University of Waterloo - Waterloo, Ontario, Canada - N2L 3B5 | ------------------------------------------------------------------