Member function pointer to member function of another class

Discussion in 'C++' started by Praetorian, Apr 2, 2008.

  1. Praetorian

    Praetorian Guest

    Hi,
    I'm having huge syntax problem dealing with function pointers. Here's
    what I'm doing:

    I have 2 classes, ClassA and ClassB. ClassA owns an instance of
    ClassB. What I want to do is pass a function pointer to a member
    function of ClassB as a parameter to a member function of ClassA. 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.

    This is the code I have:

    class ClassB {
    public:
    BOOL GetFlagX(void) { return m_bFlagX;};
    private:
    BOOL m_bFlagX;
    };

    class ClassA {
    public:
    typedef BOOL (ClassA::*FPAbortFlag)(void);
    FPAbortFlag m_fpAbort;

    protected:
    ClassB *m_pClassB;
    BOOL ClassAMemFcn(FPAbortFlag fpAbort);
    };

    In this case ClassA has new'd an instance of ClassB. What I want to do
    is have ClassA's function pointer 'm_fpAbort' point to ClassB's
    'GetFlagX' function. Can't seem to figure out the syntax for this.

    I did get the following to compile but it wasn't pointing to the
    member function associated with ClassA's instance of ClassB:

    m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));

    How do I do this?

    Thanks in advance,
    Ashish.
     
    Praetorian, Apr 2, 2008
    #1
    1. Advertising

  2. Praetorian wrote:
    > Hi,
    > I'm having huge syntax problem dealing with function pointers. Here's
    > what I'm doing:
    >
    > I have 2 classes, ClassA and ClassB. ClassA owns an instance of
    > ClassB. What I want to do is pass a function pointer to a member
    > function of ClassB as a parameter to a member function of ClassA. 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.
    >
    > This is the code I have:
    >
    > class ClassB {
    > public:
    > BOOL GetFlagX(void) { return m_bFlagX;};
    > private:
    > BOOL m_bFlagX;
    > };
    >
    > class ClassA {
    > public:
    > typedef BOOL (ClassA::*FPAbortFlag)(void);
    > FPAbortFlag m_fpAbort;
    >
    > protected:
    > ClassB *m_pClassB;
    > BOOL ClassAMemFcn(FPAbortFlag fpAbort);
    > };
    >
    > In this case ClassA has new'd an instance of ClassB. What I want to do
    > is have ClassA's function pointer 'm_fpAbort' point to ClassB's
    > 'GetFlagX' function. Can't seem to figure out the syntax for this.
    >
    > I did get the following to compile but it wasn't pointing to the
    > member function associated with ClassA's instance of ClassB:
    >
    > m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));


    There should be no need for the cast or for the parentheses.

    m_fpAbort = &ClassB::GetFlagX;

    If this doesn't work for you, post the code so we can take a closer
    look (even copy-and-paste it locally and compile). See FAQ 5.8.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 2, 2008
    #2
    1. Advertising

  3. Praetorian

    Guest

    On Apr 2, 12:05 pm, Praetorian <> 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
     
    , Apr 2, 2008
    #3
  4. Praetorian

    Guest

    On Apr 2, 12:14 pm, "Victor Bazarov" <> wrote:
    > Praetorian wrote:
    > > I did get the following to compile but it wasn't pointing to the
    > > member function associated with ClassA's instance of ClassB:

    >
    > > m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));

    >
    > There should be no need for the cast or for the parentheses.
    >
    > m_fpAbort = &ClassB::GetFlagX;



    The problem is that his FPAbortFlag is actually:

    typedef BOOL (ClassA::*FPAbortFlag)(void);

    Pointer to ClassA member, not ClassB.

    Jason
     
    , Apr 2, 2008
    #4
  5. Praetorian

    Guest

    In my example for your second option I wrote:

    > class ClassA {
    > public:
    > void DoSomething () {
    > if (m_fpAbort) m_fpAbort->FPAbort();
    > }


    But to be consistent with what I described, remove the "if
    (m_fpAbort)":

    public:
    void DoSomething () {
    assert(m_fpAbort != NULL);
    m_fpAbort->FPAbort();
    }

    It doesn't matter one way or the other, whichever is more appropriate;
    but I *did* describe "changing the rules" for a ClassA, so I should
    stick to them for consistency.

    Jason
     
    , Apr 2, 2008
    #5
  6. Praetorian

    Praetorian Guest

    On Apr 2, 10:14 am, "Victor Bazarov" <> wrote:
    > Praetorian wrote:
    > > Hi,
    > > I'm having huge syntax problem dealing withfunctionpointers. Here's
    > > what I'm doing:

    >
    > > I have 2 classes, ClassA and ClassB. ClassA owns an instance of
    > > ClassB. What I want to do is pass afunctionpointerto amember
    > >functionof ClassB as a parameter to amemberfunctionof ClassA. I
    > > don't want ClassA'smemberfunctionto call ClassB'sfunctiondirectly
    > > 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 afunction
    > >pointerI can handle that case easily.

    >
    > > This is the code I have:

    >
    > >classClassB {
    > > public:
    > > BOOL GetFlagX(void) { return m_bFlagX;};
    > > private:
    > > BOOL m_bFlagX;
    > > };

    >
    > >classClassA {
    > > public:
    > > typedef BOOL (ClassA::*FPAbortFlag)(void);
    > > FPAbortFlag m_fpAbort;

    >
    > > protected:
    > > ClassB *m_pClassB;
    > > BOOL ClassAMemFcn(FPAbortFlag fpAbort);
    > > };

    >
    > > In this case ClassA has new'd an instance of ClassB. What I want to do
    > > is have ClassA'sfunctionpointer'm_fpAbort' point to ClassB's
    > > 'GetFlagX'function. Can't seem to figure out the syntax for this.

    >
    > > I did get the following to compile but it wasn't pointing to the
    > >memberfunctionassociated with ClassA's instance of ClassB:

    >
    > > m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));

    >
    > There should be no need for the cast or for the parentheses.
    >
    > m_fpAbort = &ClassB::GetFlagX;
    >
    > If this doesn't work for you, post the code so we can take a closer
    > look (even copy-and-paste it locally and compile). See FAQ 5.8.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    Victor,
    That didn't work; I get the following compiler error:

    error C2440: '=' : cannot convert from 'BOOL (__thiscall
    CBootLoaderDlg::* )(void)' to 'CFlashDownload::FPFlashAbort'
    Types pointed to are unrelated; conversion requires
    reinterpret_cast, C-style cast or function-style cast

    I tried the reinterpret_cast suggestion as follows:

    m_fpAbortFlash = reinterpret_cast <FPFlashAbort>
    &CBootLoaderDlg::GetDlgCancelledFlag;

    That compiles but the function never returns true; even though I can
    breakpoint and verify that the flag is set. It looks like it isn't
    pointing to the correct instance of CBootLoaderDlg.

    Here are snippets of the actual code:

    In FlashDownload.h

    #include "BootLoader.h"
    #include "BootLoaderDlg.h"

    class CFlashDownload
    {
    public:
    /* Constructor/Destructor */
    CFlashDownload();
    ~CFlashDownload();

    void FlashDownloadWithUI(void);
    private:
    CBootLoaderDlg *m_pBootDlg;

    typedef BOOL (CFlashDownload::*FPFlashAbort)();
    FPFlashAbort m_fpAbortFlash;

    BOOL Flash2812InternalRam(FPFlashAbort fpAbortFlash);
    };

    In BootloaderDlg.h

    class CBootLoaderDlg : public CDialog
    {
    DECLARE_DYNAMIC(CBootLoaderDlg)

    public:
    BOOL GetDlgCancelledFlag(void) { return m_bDlgCancelled; };
    private:
    BOOL m_bDlgCancelled;
    };

    In FlashDownload.cpp

    void CFlashDownload::FlashDownloadWithUI(void)
    {
    if( m_pBootDlg != NULL ) {
    AfxMessageBox( _T("Recursive call to FlashDownloadWithUI()
    detected") );
    AfxThrowUserException();
    }

    m_pBootDlg = new CBootLoaderDlg();
    m_pBootDlg->Create( IDD_MAIN_DLG, AfxGetMainWnd() );

    m_fpAbortFlash = &CBootLoaderDlg::GetDlgCancelledFlag;
    /* Call flash download function */
    Flash2812InternalRam(m_fpAbortFlash);

    m_pBootDlg->DestroyWindow();
    delete m_pBootDlg;
    }

    CBootLoaderDlg sets m_bDlgCancelled when the dialog is cancelled
    (within its OnCancel()) method).

    Thanks for your help, I really appreciate it. Sorry for this silly
    question but you mentioned I should look at section 5.8 of the C++ FAQ
    but how do I get to the FAQ?

    Ashish.
     
    Praetorian, Apr 2, 2008
    #6
  7. Praetorian wrote:
    > [..]
    > Here are snippets of the actual code:
    >
    > In FlashDownload.h
    >
    > #include "BootLoader.h"
    > #include "BootLoaderDlg.h"
    >
    > class CFlashDownload
    > {
    > public:
    > /* Constructor/Destructor */
    > CFlashDownload();
    > ~CFlashDownload();
    >
    > void FlashDownloadWithUI(void);


    Drop the second 'void'. Make it look different from the constructor
    and the destructor, which isn't true -- all of them do NOT take any
    arguments.

    > private:
    > CBootLoaderDlg *m_pBootDlg;
    >
    > typedef BOOL (CFlashDownload::*FPFlashAbort)();
    > FPFlashAbort m_fpAbortFlash;


    Why is 'm_fpAbortFlash' is a member of CFlashDownload? If you
    intend to call it with 'm_pBootDlg' that is of type 'CBootLoaderDlg',
    then it would seem logical to make 'FPFlashAbort' to be a typedef
    for "a pointer to member of 'CBootLoaderDlg'", no?

    >
    > BOOL Flash2812InternalRam(FPFlashAbort fpAbortFlash);
    > };
    >
    > In BootloaderDlg.h
    >
    > class CBootLoaderDlg : public CDialog
    > {
    > DECLARE_DYNAMIC(CBootLoaderDlg)
    >
    > public:
    > BOOL GetDlgCancelledFlag(void) { return m_bDlgCancelled; };


    Drop the 'void' please.

    > private:
    > BOOL m_bDlgCancelled;
    > };
    >
    > In FlashDownload.cpp
    >
    > void CFlashDownload::FlashDownloadWithUI(void)


    Drop the 'void'.

    > {
    > if( m_pBootDlg != NULL ) {
    > AfxMessageBox( _T("Recursive call to FlashDownloadWithUI()
    > detected") );
    > AfxThrowUserException();
    > }
    >
    > m_pBootDlg = new CBootLoaderDlg();
    > m_pBootDlg->Create( IDD_MAIN_DLG, AfxGetMainWnd() );
    >
    > m_fpAbortFlash = &CBootLoaderDlg::GetDlgCancelledFlag;
    > /* Call flash download function */
    > Flash2812InternalRam(m_fpAbortFlash);
    >
    > m_pBootDlg->DestroyWindow();
    > delete m_pBootDlg;
    > }
    >
    > CBootLoaderDlg sets m_bDlgCancelled when the dialog is cancelled
    > (within its OnCancel()) method).


    OK...

    > Thanks for your help, I really appreciate it. Sorry for this silly
    > question but you mentioned I should look at section 5.8 of the C++ FAQ
    > but how do I get to the FAQ?


    How long have you been reading this newsgroup?

    http://www.parashift.com/c -faq-lite/

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 2, 2008
    #7
  8. Praetorian

    Praetorian Guest

    On Apr 2, 11:25 am, ""
    <> wrote:
    > On Apr 2, 12:05 pm, Praetorian <> wrote:
    >
    > > I
    > > don't want ClassA'smemberfunctionto call ClassB'sfunctiondirectly
    > > 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 afunction
    > >pointerI can handle that case easily.

    > ...
    > >classClassA {
    > > 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 apointerto amemberfunctionin ClassA. That is a
    > distinctly different type than apointerto amemberfunctionin
    > ClassB. Your FPAbortFlag can not store pointers to any other functions
    > besides ones that are members of ClassA -- meaning it can't store apointerto a ClassBfunction, and it can't store apointerto a non-memberfunctioneither (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 apointerto a ClassBmember. 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 baseclassthat
    > 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 baseclassClassB inherits from (i.e. don't let
    > it sometimes be used with one, and sometimes be used without one). For
    > example:
    >
    > === BEGIN EXAMPLE ===
    >
    > classFPAbortHandler {
    > public:
    > virtual BOOL FPAbort () = 0;
    >
    > };
    >
    > classClassB : public FPAbortHandler {
    > public:
    > BOOL FPAbort () { }
    >
    > };
    >
    > classClassA {
    > 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 thepointer-to-memberfunctionto give options of whatmemberfunctionto 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 baseclassfor 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 ===
    >
    > classClassA {
    > ...
    > public:
    > void DoSomething () {
    > ...
    > DoIt();
    > ...
    > }
    > protected:
    > virtual void DoIt () = 0;
    > ...
    > };
    >
    > classClassAWithB : public ClassA {
    > ...
    > private:
    > typedef BOOL (ClassB::*FPAbortFlag)(void);
    > ClassB *m_pClassB;
    > FPAbortFlag *m_fpAbort;
    > protected:
    > void DoIt () { m_pClassB->*m_fpAbort(); }
    > ...
    > };
    >
    > classClassAWithOtherFunction : 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()functiondoes 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:
    >
    > voidfunction(ClassA *a) {
    > a->DoSomething();
    >
    > }
    >
    > And you can pass anything to thatfunction(), and the right thing will
    > always happen.
    >
    > Hope that helps, or at least is coherent,
    > Jason


    Jason,
    I like the solution of creating another class that both the other
    classes inherit from and have it handle the function pointers. The
    problem with that implementation in my case is that both the classes I
    described are in a DLL; the DLL has 2 interfaces, one which causes
    ClassA to create an instance of ClassB or a second interface where the
    ClassA member function in question must be able to accept a function
    pointer (which may be to a member function of an arbitrary class). In
    that case, it wouldn't be possible to have the user of the DLL
    inheriting from a class which is hidden with the DLL itself. Maybe my
    approach to this problem is incorrect; I'm not a C programmer, not
    very good with C++, so there probably is a better way to do this. What
    I ideally want is a C-like way of passing around function pointers
    that can be called by anyone.

    Ashish.
     
    Praetorian, Apr 2, 2008
    #8
  9. Praetorian

    Jim Langston Guest

    Praetorian wrote:
    > On Apr 2, 11:25 am, ""
    > <> wrote:
    >> On Apr 2, 12:05 pm, Praetorian <> wrote:
    >>
    >>> I
    >>> don't want ClassA'smemberfunctionto call ClassB'sfunctiondirectly
    >>> 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
    >>> afunction pointerI can handle that case easily.

    >> ...
    >>> classClassA {
    >>> 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 ...

    [SNIP]
    >
    > Jason,
    > I like the solution of creating another class that both the other
    > classes inherit from and have it handle the function pointers. The
    > problem with that implementation in my case is that both the classes I
    > described are in a DLL; the DLL has 2 interfaces, one which causes
    > ClassA to create an instance of ClassB or a second interface where the
    > ClassA member function in question must be able to accept a function
    > pointer (which may be to a member function of an arbitrary class). In
    > that case, it wouldn't be possible to have the user of the DLL
    > inheriting from a class which is hidden with the DLL itself. Maybe my
    > approach to this problem is incorrect; I'm not a C programmer, not
    > very good with C++, so there probably is a better way to do this. What
    > I ideally want is a C-like way of passing around function pointers
    > that can be called by anyone.


    There is a problem with that. A class function has a hidden first parameter
    called this which is a pointer to the instance of the class.

    I.E.

    class Foo
    {
    void MyFunc( int i );
    };

    MyFunc has a hidden first parameter this which would look like this if it
    was spelled out:
    void MyFunc( Foo* this, int i );

    When you declare a class function pointer the compiler knows about the
    hidden this pointer.

    Now the problems.

    You can not mix pointers between classes as you are trying to do because the
    compiler has to know what parameters the function accepts. Is the first
    parameter ClassA*, ClassB or no hidden first parameter (stand alone
    function).

    You might be able to get away with some form of void* as the first
    parameter, but I doubt it. Also, what about stand alone functions that
    don't have a hidden first parameter?

    You might just want to go with stand alone function pointers and accept a
    void* to the instance if required, although if this is a call back function
    how is your calling function going to know what to place?

    I think you might want to rethink your program design.

    --
    Jim Langston
     
    Jim Langston, Apr 3, 2008
    #9
  10. Praetorian

    James Kanze Guest

    On Apr 2, 6:05 pm, Praetorian <> wrote:

    > I'm having huge syntax problem dealing with function pointers.
    > Here's what I'm doing:


    > I have 2 classes, ClassA and ClassB. ClassA owns an instance
    > of ClassB. What I want to do is pass a function pointer to a
    > member function of ClassB as a parameter to a member function
    > of ClassA. 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.


    > This is the code I have:


    > class ClassB {
    > public:
    > BOOL GetFlagX(void) { return m_bFlagX;};
    > private:
    > BOOL m_bFlagX;
    > };


    > class ClassA {
    > public:
    > typedef BOOL (ClassA::*FPAbortFlag)(void);
    > FPAbortFlag m_fpAbort;


    > protected:
    > ClassB *m_pClassB;
    > BOOL ClassAMemFcn(FPAbortFlag fpAbort);
    > };


    > In this case ClassA has new'd an instance of ClassB. What I
    > want to do is have ClassA's function pointer 'm_fpAbort' point
    > to ClassB's 'GetFlagX' function. Can't seem to figure out the
    > syntax for this.


    > I did get the following to compile but it wasn't pointing to
    > the member function associated with ClassA's instance of
    > ClassB:


    > m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));


    Could you please explain what you mean by that last sentence?
    &(ClassB::GetFlagX) definitely points to a member function of
    ClassB. The conversion doesn't change that. (Of course, the
    only thing you can legally do with the converted pointer is cast
    it back to the original type, and invoke it through a pointer to
    ClassB.) And pointers to members aren't associated with any
    instance, so saying that it should point to a specific instance
    doesn't make sense.

    If what you want is to pass someone who only knows about ClassA
    a pointer to a ClassA and a pointer to member of ClassA, then
    all that someone can do is invoke a function of ClassA. If you
    want it to invoke a function on the ClassB instance owned by the
    ClassA instance you passed it, you'll have to create a
    forwarding function in ClassA, and pass a pointer to member to
    it. Most of the time, however, it is better to provide some
    sort of functional object, and handle all of the indirections
    there, rather than to confuse the issue with pointers to member
    functions and such.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 3, 2008
    #10
  11. Praetorian

    Praetorian Guest

    On Apr 3, 2:38 am, James Kanze <> wrote:
    > On Apr 2, 6:05 pm, Praetorian <> wrote:
    >
    >
    >
    > > I'm having huge syntax problem dealing with function pointers.
    > > Here's what I'm doing:
    > > I have 2 classes, ClassA and ClassB. ClassA owns an instance
    > > of ClassB. What I want to do is pass a function pointer to a
    > > member function of ClassB as a parameter to a member function
    > > of ClassA. 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.
    > > This is the code I have:
    > > class ClassB {
    > > public:
    > > BOOL GetFlagX(void) { return m_bFlagX;};
    > > private:
    > > BOOL m_bFlagX;
    > > };
    > > class ClassA {
    > > public:
    > > typedef BOOL (ClassA::*FPAbortFlag)(void);
    > > FPAbortFlag m_fpAbort;
    > > protected:
    > > ClassB *m_pClassB;
    > > BOOL ClassAMemFcn(FPAbortFlag fpAbort);
    > > };
    > > In this case ClassA has new'd an instance of ClassB. What I
    > > want to do is have ClassA's function pointer 'm_fpAbort' point
    > > to ClassB's 'GetFlagX' function. Can't seem to figure out the
    > > syntax for this.
    > > I did get the following to compile but it wasn't pointing to
    > > the member function associated with ClassA's instance of
    > > ClassB:
    > > m_fpAbort = (FPAbortFlag)(&(ClassB::GetFlagX));

    >
    > Could you please explain what you mean by that last sentence?
    > &(ClassB::GetFlagX) definitely points to a member function of
    > ClassB. The conversion doesn't change that. (Of course, the
    > only thing you can legally do with the converted pointer is cast
    > it back to the original type, and invoke it through a pointer to
    > ClassB.) And pointers to members aren't associated with any
    > instance, so saying that it should point to a specific instance
    > doesn't make sense.
    >
    > If what you want is to pass someone who only knows about ClassA
    > a pointer to a ClassA and a pointer to member of ClassA, then
    > all that someone can do is invoke a function of ClassA. If you
    > want it to invoke a function on the ClassB instance owned by the
    > ClassA instance you passed it, you'll have to create a
    > forwarding function in ClassA, and pass a pointer to member to
    > it. Most of the time, however, it is better to provide some
    > sort of functional object, and handle all of the indirections
    > there, rather than to confuse the issue with pointers to member
    > functions and such.
    >
    > --
    > James Kanze (GABI Software) email:
    > Conseils en informatique orientée objet/
    > Beratung in objektorientierter Datenverarbeitung
    > 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


    James,
    Thanks for your reply. I figured out the problem with my original
    posting. The function pointer needed to be a member of ClassB since it
    was pointing to a ClassB member function. What I really want to do is
    to be able to accept any arbitrary function pointer that has been
    passed to a ClassA member function and call the function pointed to by
    the pointer. Both ClassA and ClassB are part of a DLL and so I'll have
    no prior knowledge of the type of function pointer being passed to me.
    It could be a pointer to some other class' member function or to a
    standalone function. This is easy to do in C because function pointers
    do not belong to a class in that case. Your suggestion about providing
    a functional object to handle indirection is interesting; sounds like
    that's what I need. Could you please elaborate on this further or
    point me to where I can find more information on this? I really
    appreciate your help.

    Ashish.
     
    Praetorian, Apr 3, 2008
    #11
  12. Praetorian

    James Kanze Guest

    On 3 avr, 16:33, Praetorian <> wrote:
    > On Apr 3, 2:38 am, James Kanze <> wrote:


    [...]
    > Your suggestion about providing
    > a functional object to handle indirection is interesting; sounds like
    > that's what I need. Could you please elaborate on this further or
    > point me to where I can find more information on this? I really
    > appreciate your help.


    I'm not sure if it's ever really been documented as a pattern;
    it was widespread before patterns became widely known.
    Basically, your class defines an abstract base class:

    class AbstractCallback
    {
    public:
    virtual AbstractCallback() {}
    virtual void operator()() const = 0 ;
    } ;

    and the function the client calls looks something like:

    void registerCallback( AbstractCallback const& cb ) ;

    The client then derives from AbstractCallback, and passes an
    instance of the derived class.

    For convenience, you could even provide a template for the
    concrete class:

    template< typename T, void (T::*fnc)() >
    class Callback : public AbstractCallback
    {
    public:
    explicit Callback( T* object )
    : myObj( object )
    {
    }

    virtual void operator()() const
    {
    (myObj->*fnc)() ;
    }

    private:
    T* myObj ;
    } ;

    The user then creates an instance of Callback< MyClass,
    &MyClass::whatever >( this ), and passes you it. (Long before
    templates, we used a macro for the derived class.)

    Alternatively, your function could be a template, taking a
    functional object. But I rather think you'd have problems
    bundling that into a DLL.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 3, 2008
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,954
    Thomas Weidenfeller
    Oct 12, 2005
  2. Newsgroup - Ann
    Replies:
    5
    Views:
    668
    John Carson
    Jul 30, 2003
  3. Fraser Ross
    Replies:
    4
    Views:
    1,098
    Fraser Ross
    Aug 14, 2004
  4. Replies:
    12
    Views:
    737
    fluden
    Feb 11, 2005
  5. somenath
    Replies:
    2
    Views:
    179
    somenath
    Aug 29, 2013
Loading...

Share This Page