wilson@brillig.cs.umd.edu (Anne Wilson) (11/08/90)
(I tried to post this yesterday, and it has not yet appeared.  My
apologies if this appears twice. -aw)
AUGHH!
I am having a devil of a time trying to invoke a pointer to member function
through an object which is a base class object for the derived class to
which the member function belongs.  The whole thing is so compliciated,
I have tried to "paraphrase" an example:
class Base_class {
}
class Derived_class : public class {
	void new_function;
}
typedef void (*v_fn_ptr) (void *);
class Container_class {
	Base_class* *list;	// array of pointers to Base_class elements
	Container_class (int obj_count, ... );
	void apply (v_fn_ptr);	// apply function to each element in list
}
Derived_class D1, D2;
Container_class c (2, &D1, &D2);		// create c
// Idea is to apply new_function to both D1 and D2
c.apply (&Derived_class::new_function);		// compiles, but crashes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I have running code which does something very similar and works correctly,
the only difference being that the apply function is called on Base_class
objects rather than Derived_class objects.  So I suspect the binding between
the Derived_class member function and a list item, which is also of type 
Derived_class, is not happening properly.
I have been trying the trick of letting the function appear like any old function
and passing it the address of the Derived_class object as its first argument,
but to no avail.  I typed in the following example from Straustrup, and (guess 
what ...) it ran fine.
#include <stream.h>
class cl
{
public:
	char* val;
	void print (int x) { cout << val << " " << x << nl;};
	cl (char *v) {val = v;}
};
typedef void (*PROC) (void*, int);
main () {
	cl z1 ("z1");
	cl z2 ("z2");
	PROC pf1 = PROC (&z1.print);
	PROC pf2 = PROC (&z2.print);
	z1.print(1);
	(*pf1) (&z1,2);
	z2.print(3);
	(*pf2) (&z2,4);
}
Can anyone help with this??  I am running g++ V 1.37.1 on a VAX.
I would be **very** grateful for any suggestions!
Anne Wilsonfuchs@it.uka.de (Harald Fuchs) (11/09/90)
wilson@brillig.cs.umd.edu (Anne Wilson) writes: >(I tried to post this yesterday, and it has not yet appeared. My >apologies if this appears twice. -aw) Not here. >class Base_class { >} >class Derived_class : public class { > void new_function; >} >typedef void (*v_fn_ptr) (void *); >class Container_class { > Base_class* *list; // array of pointers to Base_class elements > Container_class (int obj_count, ... ); > void apply (v_fn_ptr); // apply function to each element in list >} >Derived_class D1, D2; >Container_class c (2, &D1, &D2); // create c >// Idea is to apply new_function to both D1 and D2 >c.apply (&Derived_class::new_function); // compiles, but crashes >Can anyone help with this?? I am running g++ V 1.37.1 on a VAX. >I would be **very** grateful for any suggestions! Use real "pointers to members". If you don't know what that is, get a newer C++ book (they were added to the language after 1985). Then it goes something like that: #include <iostream.h> #include <stdarg.h> class Base_class { public: virtual void dfunc () = 0; }; class Derived_class: public Base_class { int d; public: Derived_class (int x): d (x) {} void dfunc () { cout << "Derived_class\t" << d << "\n"; } }; class Container_class { int num; Base_class** list; public: Container_class (int, ...); void apply (void (Base_class::*) ()); }; Container_class::Container_class (register int x, ...): num (x), list (new Base_class*[num]) { cout << num << " elements:"; va_list ap; va_start (ap, x); register Base_class** p = list; while (x--) { *p++ = va_arg (ap, Derived_class*); cout << " " << p[-1]; } va_end (ap); cout << "\n"; } void Container_class::apply (void (Base_class::*funcp) ()) { register int n = num; register Base_class** p = list; // while (n--) ((*p++)->*funcp) (); // Too complicated for AT&T cfront 2.1 while (n--) ((*p)->*funcp) (), p++; } main () { Derived_class D1 (1), D2 (2); cout << "D1@" << &D1 << ", D2@" << &D2 << "\n"; Container_class c (2, &D1, &D2); c.apply (&Base_class::dfunc); } Note that you can only apply a member function of the base class to a Base_class* object, but it can be a virtual member function. -- Harald Fuchs <fuchs@it.uka.de> <fuchs%it.uka.de@relay.cs.net> ... <fuchs@telematik.informatik.uni-karlsruhe.dbp.de> *gulp*
kaiser@ananke.stgt.sub.org (Andreas Kaiser) (11/09/90)
In your msg to All, dated <09 Nov 90 08:33>, it said:
 AW> I am having a devil of a time trying to invoke a pointer to member
 AW> function through an object which is a base class object for the
 AW> derived class to which the member function belongs.  The whole thing
 AW> is so compliciated, I have tried to "paraphrase" an example:
You cannot invoke non-static member functions via normal function 
pointers. Member functions have a hidden first argument ("this"). 
For this reason, the C++ language has a special function pointer 
type, the "pointer to member function".
Example:
 class Base_class {
 };
 typedef void (Base_class::*v_fn_ptr)(void);
// This is a pointer to a member function of
// class "Base_class" or it's descendants.
 class Derived_class : public class {
        void new_function();
 };
 class Container_class {
         Base_class *list;
         Container_class (int obj_count, ... );
         void apply (v_fn_ptr);
 };
 Derived_class D1, D2;
 Container_class c (2, &D1, &D2);
Now, if you want to run "apply":
         c.apply (Derived_class::new_function);
and within "apply", this function is called by:
         (list->*function_ptr)();
                Andreas
--  
:::::::::::::::::::: uucp: kaiser@ananke.stgt.sub.org
:: Andreas Kaiser :: fido: 2:509/5.2512 & 2:507/18.7206
::::::::::::::::::::jbuck@galileo.berkeley.edu (Joe Buck) (11/10/90)
In article <fuchs.658164606@t5000>, fuchs@it.uka.de (Harald Fuchs) writes: > [ in answer to a query by Anne Wilson ] > Use real "pointers to members". If you don't know what that is, get a > newer C++ book (they were added to the language after 1985). The best book I have seen for explaining pointers to member functions is Lippman's "C++ Primer" (I highly recommend this book). Several introductory C++ books omit the concept entirely! Throw away such books. -- Joe Buck jbuck@galileo.berkeley.edu {uunet,ucbvax}!galileo.berkeley.edu!jbuck
mjv@objects.mv.com (Michael J. Vilot) (11/10/90)
Anne Wilson asks for help: > I am having a devil of a time trying to invoke a pointer to member function > through an object which is a base class object for the derived class to > which the member function belongs. class Base_class { ... }; class Derived_class : public Base_class { void new_function(); }; typedef void (*v_fn_ptr) (void *); !! This is declaring a type named `v_fn_ptr' which points to a _non_ member !! function. class Container_class { ... void apply (v_fn_ptr); !! This declares a function taking a non-member function pointer }; c.apply (&Derived_class::new_function); // compiles, but crashes !! This should fail at compile time: it is placing a pointer of type !! `void (Derived_class::*)(void)' into a pointer of type `void (*)(void*)' !! It would make more sense to declare the type of `v_fn_ptr' as: typedef void (Base_class::* v_fn_ptr)(); > I have been trying the trick of letting the function appear like any old function > and passing it the address of the Derived_class object as its first argument, > but to no avail. I typed in the following example from Straustrup, and (guess > what ...) > > typedef void (*PROC) (void*, int); > It's a non-portable approach, at best. The example you cite, from ``The C++ Programming Language'' Section 5.4.5, has a footnote in the version of the book I have (second printing, March 1986): ``Later versions of C++ support a concept of pointer to member; cl::* means "pointer to member of cl". For example, typedef void (cl::*PROC)(int)'' Note the difference in type between this declaration, and the one above. Hope this helps, -- Mike Vilot, ObjectWare Inc, Nashua NH mjv@objects.mv.com (UUCP: ...!decvax!zinn!objects!mjv)