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 Wilson
fuchs@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)