> Hi Rooters!
> I have a C++ question....It is related to pointer to functions of a
> class. I want define in a base class a method (name RK in the example)
> which used pointer to methods of a derived class...and I don't now how
> to do. Here is what I do (and which of course don't work):
>
> the base class A:
>
> class A {
> void (*Fct)(double t,double *X,double *dX);
> void RK(...);
> };
> RK methods use the pointer Fct.
>
> then a class B:
>
> class B : public A {
> ...
> void EDP1(double t,double *X,double *dX);
> void EDP2(double t,double *X,double *dX);
> void Evol(...);
> };
>
> Now in the method Evol(...) I want to use A::RK(...) with either EDP1 or
> EDP2 for the pointer Fct (e.g. Fct=EDP1) but the cast don't work.
>
> Is there any way to do what I want?
Sort of. First of all, you need to use the pointer-to-member syntax. To
declare a pointer-to-member of a class, you use:
void (B::* Fct)(double t, double *X, double *dX);
(Fct is a pointer to a member of B which is a function taking double,
double*, double* and returning void).
If b is an instance of B, you would call the function pointed to with
Fct with:
b.*Fct(t,&x,&dx);
Likewise if pb is a pointer to an instance of b, you would use:
pb->*Fct(t,&x,&dx);
Okay, so far so good. Problems will arise though, because the
inheritance scheme for pointer-to-function is contravariant. That is to
say, a pointer-to-member-of-Base can be cast to a pointer-to-member-of-D
erived, but not the other way around. This seems backwards at first,
but is necessary for correct behavior.
The reason for this is simple: if a is a Derived::*, you have no way of
knowing whether it was originally defined in the Base class or in the
Derived class. But if it were defined in the Derived class, you may not
be able to meaningfully call it with an object of type Base, or of some
other derived class of Base. The converse, however, is true; if the
object is Derived, you know you can meaningfully execute Base class
functions.
The upshot is that you won't be able to assign EDP1 or EDP2 to the
variable Fct in class A, if Fct were defined as pointer-to-member of A.
You have a few choices for solutions:
1) Avoid the whole problem altogether. If you don't need the object
itself inside EDP1 or EDP2, you can declare them as static. Pointers to
static member functions are just pointers to ordinary functions, and
you're done.
2) Maybe EDP1 and EDP2 really ought to be members of A, not members of
B; ie, they don't depend on any B-specific information to do their
duty. If so, it's easy and you're done.
3) If neither of those is true, you probably don't want to be using
pointers-to-members, or rather you might want to be using them, but
through the mechanism of a virtual function call inside RK, which in B
happens to use a pointer-to-member (of B, now). Remember that RK has to
be callable by any instance of A, and may not turn out to be a B
object, so other descendants of A will have to supply their own
behavior. This is exactly where a virtual function call is indicated.
You're not done; you've got some thinking to do about what really
belongs in the base class and what in the derived class, but at least
you're on your way.
On a root-related point: I have no idea how well CINT handles
pointers-to-members. Given that it is a fairly involved syntax and
complicated language issue, I would be very careful using this kind of
code in CINT until I was convinced that it worked right.
George Heintzelman
georgeh@aya.yale.edu
This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:39 MET