EarthWeb
Developer.com
Find:
 


SEARCH TECHCRAWLER -----
CodeGuru Links
Visual Basic
Visual C++

Discussion Boards
Book Reviews
Newsletters (subscribe)
Newsletters (archived)
Guru Columns
  • Nothing but .NET
  • Bugs in the Machine
  • The Shell Game
  • Into the IUnknown
  • The Working Class Programming
  • Tempting Templates
  • Programming in the Real World
  • Article Sections
    ATL COM ActiveX
    atl com activex
    shell programming
    C++
    algorithms & formulas
    c++ & mfc
    date & time
    string
    Controls
    button control
    combobox
    edit control
    imagelist control
    listbox control
    listview control
    menu
    other controls
    property sheet
    rich edit control
    static control
    status bar
    toolbar
    treeview control
    Database
    database
    Frameworks
    ui & printing frameworks
    Graphics & Multimedia
    bitmaps & palettes
    directx
    gdi
    multimedia
    opengl
    Internet & Networking
    ie programming
    internet protocols
    isapi
    network protocols
    Visual Studio
    add-ins & macros
    editor tips
    Windows Programming
    ce
    clipboard
    dll
    file & folder
    help systems
    printing
    win32
    system
    Windows & Dialogs
    console
    dialog
    docking window
    doc/view
    splitter
    Interact
    Newsletters
    Guestbook
    Recommend Us!
    About Us




    EarthWeb Sites:
    IT Management
    Networking & Telecommunications
    IT Jobs
    Software Development
    Web Development
    Hardware & Systems
    Community & SIGs
    EarthWeb Worldwide
       

    Function Pointers to Non-Static Object Methods


    This article was contributed by Andrew Schafer.

    One of the first things that I noticed when learning C++, was that function pointers had become much more difficult to use with object architecture. Each function/method needs to know what object it is part of.  So, to point to an object's method, we also must know about an object. Using the data from each, we can freely call any method of any object, without knowing exactly what we are calling.

    The code I have included is a holder class that takes a pointer to an object and a pointer to a method.  Either can be changed at any time. During the lifetime of the holder class object, a helper method can be called that calls the stored method pointer.   Its that simple...Sort-of.  The syntax can get a little confusing, but I'll try to walk you through.

    First, an abstract base class is defined.  The CMethodPtr class is derived from this class, but this class is used to pass the data around between functions. You'll see what I mean later.

    // R is the return type
    template <class R>
    class CMethodPtrBase
    {
    public:
        virtual R CallMethod() = 0;
        virtual R CallMethod(LPVOID arg1) = 0;
        virtual R CallMethod(LPVOID arg1, LPVOID arg2) = 0;
    };

    Next is the derived class.  Both the abstract base class and the derived class require the return type of the function being held.  The derived class requires another template argument declaring the type of object this holder will store. Neither of these can be changed once the holder has been declared.

    The constructor takes a pointer to the actual object( not the definition like above) that contains the method we will call. It also takes a pointer to the method.  The METHOD macro is used to easily pass the method into the holder.

    The CallMethod() methods are the helper methods for calling the method that the holder object contains.  The different versions are for different numbers of arguments.   If more arguments are needed, then add new functions to the abstract base class and to this class.

    // r = return type
    // o = object definition
    // m = method
    #define METHOD(r,o,m) (r (o::*)() )(&o::m)

    // O = object definition
    // R = return type
    template <class O, class R>
    class CMethodPtr : public CMethodPtrBase<R>
    {
        typedef R (O::*PMETHOD)();
        typedef R (O::*PMETHOD1)(LPVOID);
        typedef R (O::*PMETHOD2)(LPVOID, LPVOID);

    public:
        CMethodPtr(O* pObject, PMETHOD pMethod) : m_pObject( pObject ), m_pMethod( pMethod ) {};

        // Member Variables
    private:
        O*    m_pObject;    // pointer to an object
        PMETHOD    m_pMethod;    // pointer to the method

        //Implementation
    public:
        void SetObject( O* pObject ) { m_pObject = pObject; }
        void SetMethod( PMETHOD pMethod ) { m_pMethod = pMethod; }

        // 0 args
        virtual R CallMethod()
        {
            return (m_pObject->*m_pMethod)();
        }

        // 1 arg
        virtual R CallMethod(LPVOID arg1)
        {
            return (m_pObject->*(PMETHOD1)m_pMethod)(arg1);
        }

        // 2 args
        virtual R CallMethod(LPVOID arg1, LPVOID arg2)
        {
            return (m_pObject->*(PMETHOD2)m_pMethod)(arg1, arg2);
        }
    };

    That is basically it for the definition.  Here is how it is used:

    Somewhere declare the object that has the method we want to point to and the holder object:

    // A helper macro that uses the METHOD macro
    #define SUMMETHOD(m) METHOD(int, CSumObject, m)

    CSumObject m_SumObject;   // The object that has the method we want to point to
    CMethodPtr<CSumObject, int> m_SumMethodPtr( &m_SumObject, SUMMETHOD(Function2) ); // Uses a CSumObject thats returns an int

    Function2() is the method that will be held. Later on we can call that function like this:

    int nArg1 = 5;
    int nArg2 = 10;

    int nReturn;

    nReturn = m_SumMethod.CallMethod( &nArg1, &nArg2 );  // Whatever it was pointing to, we just called it

    If you want to pass a holder object through a function, define the function this way:

    int MyObject::SomeFunction( CMethodPtrBase<int> pMethodPtr )
    {
        return pMethodPtr->CallMethod();
    }

    Notice the abstract base class is used so that we do not have to know what type of class the CMethodPtr object is holding.  If we used CMethodPtr directly, the template arguments would require us to tell it what type of class the CMethodPtr object was holding.

    Take a look at the demo project or source to see a more thorough example.

    Download demo project - 15.8 KB

    Download source - 7.7 KB

    Comments:

    Date Posted: February 13, 1998

    Add Comment

       

    Give them a visit Click Here!

    Click Here!

    Get the Answers You Need!
    Incentive-based, question & answer Marketplace. The first 5,000 members receive $12 credit! Try it! Knowledge Market.

    For tons of Windows technology resources, check out the Windows Programming directory.

    Target your Technical searches with
    TechCrawler

    Sweepstakes:
    Here's your chance to win Windows 2000 Professional. EarthWeb's sweepstakes runs through July 2. Click here to enter.

    Give them a visit Click Here!

    Click Here!


    ★ wanayoo — archive 1999 http://codeguru.earthweb.com/cpp_mfc/methodpointers.shtmlNouvelle recherche | Portail wanayoo

    Home About Us Subscribe Contact Us
    Use of this site is subject to certain Terms & Conditions.
    Earthweb's statement regarding our users' right to privacy.
    Copyright ©1996-2000 EarthWeb Inc.. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited.