Re: Member function pointer to member function of another class
On Apr 2, 12:05 pm, Praetorian <ashish.sadanan...@gmail.com> wrote:
I
don't want ClassA's member function to call ClassB's function directly
because ClassA can be used in 2 ways, one of which is a case in which
it does not create an instance of ClassB; hence by passing a function
pointer I can handle that case easily.
....
class ClassA {
public:
typedef BOOL (ClassA::*FPAbortFlag)(void);
....
m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));
You can not do what you are trying to do the way you are trying to do
it. Your code compiles with the explicit cast but will not necessarily
run correctly, and the reason you need an explicit cast to get it to
compile is because the types are not compatible. You have declared
FPAbortFlag as a pointer to a member function in ClassA. That is a
distinctly different type than a pointer to a member function in
ClassB. Your FPAbortFlag can not store pointers to any other functions
besides ones that are members of ClassA -- meaning it can't store a
pointer to a ClassB function, and it can't store a pointer to a non-
member function either (which, if I understand you correctly, is
something you'll eventually want to do if ClassA has no ClassB
instance).
You have a couple of different options. One simple one is:
typedef BOOL (ClassB::*FPAbortFlag) (void);
Note that it is a pointer to a ClassB member. And then, in your ClassA
logic:
if (m_fpAbort && m_pClassB)
m_pClassB->*m_fpAbort();
else
do_the_other_thing();
A second option is to make your ClassB inherit some base class that
describes the interface you are expecting it to have, and change your
definition of ClassA a little to say that it will *always* have an
instance of whatever base class ClassB inherits from (i.e. don't let
it sometimes be used with one, and sometimes be used without one). For
example:
=== BEGIN EXAMPLE ===
class FPAbortHandler {
public:
virtual BOOL FPAbort () = 0;
};
class ClassB : public FPAbortHandler {
public:
BOOL FPAbort () { }
};
class ClassA {
public:
void DoSomething () {
if (m_fpAbort) m_fpAbort->FPAbort();
}
private:
FPAbortHandler *m_fpAbort;
};
=== END EXAMPLE ===
In that case, ClassA could handle anything that implemented the
FPAbortHandler interface, which includes ClassB, or any other object
that you may want to define. This is the way I would personally do it,
because it is a good balance between simplicity and flexibility. If
you need to use the pointer-to-member function to give options of what
member function to call, it can be a:
typedef BOOL (FPAbortHandler::*FPAbortFlag) (void);
And can point to any FPAbortHandler members.
A third option is to make your ClassA a base class for some special
derived classes, leaving the details that are different to the derived
classes. If your ClassA can be used in a few different ways, it is
also appropriate to use two different classes with the common stuff in
ClassA. For example:
=== BEGIN EXAMPLE ===
class ClassA {
...
public:
void DoSomething () {
...
DoIt();
...
}
protected:
virtual void DoIt () = 0;
...
};
class ClassAWithB : public ClassA {
...
private:
typedef BOOL (ClassB::*FPAbortFlag)(void);
ClassB *m_pClassB;
FPAbortFlag *m_fpAbort;
protected:
void DoIt () { m_pClassB->*m_fpAbort(); }
...
};
class ClassAWithOtherFunction : public ClassA {
...
private:
...
protected:
void DoIt () { ... }
...
};
=== END EXAMPLE ===
In that case, DoIt() takes care of all the differences.
ClassA::DoSomething() does a bunch of stuff and calls DoIt() for
derived-class-specific details. The DoIt() function does the right
thing. Sorry I'm being vague, but it's a general issue.
Using inheritance allows you to access everything via ClassA pointers,
as well:
ClassA *things[2];
things[0] = new ClassAWithB(MyClassB); // or whatever
things[1] = new ClassAWithOtherFunction(...);
Or, of course:
void function (ClassA *a) {
a->DoSomething();
}
And you can pass anything to that function(), and the right thing will
always happen.
Hope that helps, or at least is coherent,
Jason