Z’s

July 16, 2008

Pointer To C++ Class Methods; Or Should You Call ‘em “Method Pointers”?

This one is after a real long break from blogs :).
Function pointer is pretty commonplace among C/C++ developers unlike “pointer to C++ class methods.” For those who have never used it or even heard of it; it really is very similar to “Function Pointer” from outside, though its internal mechanism is entirely different and its syntax is quite ugly. So, without much literature, let’s see how one would make a pointer to a C++ method. Before that, let’s review the usual function pointer of C a little bit:

// define a function type FUNCTION that takes int and char* as argument

typedef int (*FUNCTION) (int, char*);

// Declare a funciton pointer f of type FUNCTION

// and make f point to some function that takes int and char* as argument.

FUNCTION f = some_function;

// Simply call the function with an int and char* argument

f(10,“Hello”);

So that’s how function pointers are dealt in C. Following is a snippet that shows how to declare a function pointer that points to a method of a C++ class and then finally shows how to call that method via the function pointer (or “method pointer,” if you like to call it that way):

// A sample class, lets call it Base

// with a sample method called “Method”

class Base{

public:

int Method( int i, char *str )

{

printf(“Inside Base::Method: %d, %s\n”,i,str);

return 0;

}

};

// Note how FNMETHOD is defined. This is very similar to C function pointer

// definition just that the type is preceded by the class name and “::”.

// The class name is important and this tells that FNMETHOD can only point to

// the methods of type (int, char*) and only of class Base and it’s derivatives.

typedef int (Base::*FNMETHOD) ( int, char* );

// Later somewhere else in the code….

// Declare a function pointer f of type FNMETHOD and make it

// point to a method of the Base class, e.g. Base::Method.

// Note the usage of & symbol and this is important. For C,& is not

// necessary for the assignment but for C++ method it is necessary.

FNMETHOD f = &Base::Method;

// Now create an object of Base

Base *pBase = new Base();

// This is how f can be called with an instance of Base. Note the syntax, with

// care give to the * operator and brackets. You must need an intance of Base

// to call f because you need to pass the “this” pointer to the methods right?

(pBase->*f)(10,“Hello”);

Can you see the resemblance between C++ “method pointers” the usual C function pointers? Obviously, I can write a whole big chapter on this “Method Pointers” and how they all work under the hood (which is quite different from function pointers of C) but I will stop it here as writing in on every detail might bore you to death. If you want to learn more, just google a little bit; you will find thousands of articles on this topic which go into extreme details. For the moment; all I can add is: this “method pointers” works perfectly for even virtual functions and derived classes. But, there is a little catch, see the following:

class Base{

public:

virtual int Method( int i, char *str )

{

printf(“Inside Base::Method: %d, %s\n”,i,str);

return 0;

}

};

// A derived class of Base with overrides Method

class Derived : public Base{

public:

virtual int Method( int i, char *str )

{

printf(“Inside Derived::Method: %d, %s\n”,i,str);

return 0;

}

};

// Note the type FNMETHOD is defined on Base class

typedef int (Base::*FNMETHOD) ( int, char* );

// HERE IS THE CATCH; Notice that f is pointing to the method of the

// Base class but eventually runtime will decide, based on the object pointer,

// which method will be called, Base::Method or Derived::Method.The

// bad thing is if Derived class overrides Base::Method then, as a matter

// of fact,FNMETHOD f = &Derived::Method will give compiler error!

FNMETHOD f = &Base::Method;

// Now create an object of Derived!

Base *pBase = new Derived();

// Verify that the Method of Derived is called!

(pBase->*f)(10,“Hello”);

If you want to know more about the above “catch” situation, then I would suggest you try out the above example yourself and experiment a lot!
Finally, you must be wondering, why would you ever need pointer to a C++ method. Honestly, you can, most of the time, avoid using it unless you are trying to implement something like MFC message mapping or something similar to the Delegates of C#. However, truest form of C# Delegate is not probably implementable using this “C++ method pointer” (correct me if I am wrong). Message mapping for GUI or other similar codes are like the perfect places for using “method pointers” where you want a particular method of a particular instance of a class to be called upon some event (like call-backs).
Just as a little homework: try to figure out and google about how C++ method pointer works under the hood and how also achieves polymorphism (as shown above).

About these ads

14 Comments »

  1. Thank you, really, thank you very much.

    This is what I can call a good tutorial.

    Comment by Victor Calderon — August 8, 2008 @ 8:08 pm | Reply

  2. hi
    and thank you for this article.
    i create Base Calss Called Object in (DOS C++ 3.0)
    in header file i defined : typedef void (Object::*EventHandler)();
    i Create Timer Class that have Tick Event(Inherited Object).
    also i Create Cursor Class(Inherited Object), in this class i create new Timer Object
    and i want te set one of TimerObject->Tick = Cursor::Timer_Tick;
    but i cant do this, how can i solve this?

    Comment by Univ2Univ.ir — December 2, 2008 @ 6:13 am | Reply

  3. Hi,

    I’ve another query related to member function and member data variables.
    Consider below example

    Class Hype{
    private:
    int data;
    public:
    int get(){return data;}
    void set(int d){data=d;}
    };
    int main()
    {
    Hype h1,h2,h3;
    int a,b,c;
    h1.set(10);
    h2.set(20);
    h3.set(30);
    a= h1.get();
    b= h2.get();
    c= h3.get();
    return 1;
    }
    w.r.t. above example I wanted to ask a weird question.
    we are calling functions of class with objects of the class.
    But how would the function know where actually the h1.data, h2,data or h3.data is stored in memory?
    because internally we are operating upon data-member of that specific object which will have different memory locations for each of them?
    So when we call h1.set(10) or h1.get() does the function gets any extra information about the objects location in memory? how?
    Can someone pls answer this question?

    Thanks
    Himanshu

    Comment by Himanshu — June 4, 2009 @ 2:38 pm | Reply

    • Yes, the function gets an extra information. Invisibly to the programmer, every non-static method receives as first argument a pointer to the object of which method is called(the “this” pointer).When you use a field from the object you write a++ but it is this->a++. When you call method trough pointer it also gets “this” pointer.

      Comment by Daniel Shaprin — November 2, 2010 @ 9:00 pm | Reply

  4. Pls let me know if someone can help me get the answer!

    Comment by Himanshu — June 4, 2009 @ 2:40 pm | Reply

  5. To Himanshu,

    By default implicitly a pointer will be passed to the methods of c++ class. That pointer is called this pointer. Your code will be internally replaced by compiler like below

    int get(){return this.data;}
    void set(int d){this.data = d;}

    that this is pointer which holds the address of the object which calls the method. Thats how it will come to know the coorect address of member variable. I hope this will help you

    Comment by Vijaya Sangameswar — November 24, 2009 @ 2:46 pm | Reply

  6. Umh, Member methods gets a “this” variable upon call, which is a pointer to the actual object.

    Comment by Josejulio — January 21, 2010 @ 2:42 am | Reply

  7. Great tutorial !

    I was searching how to use a method pointer,
    the syntax is quite unusual.

    Comment by Jacques — July 7, 2011 @ 3:39 pm | Reply

  8. do you know a work around this maybe
    I wanted to be able to centralize the code a bit more like in one of those visual language that every time you place a control and create a event, the method is created on the main form instead of a new class of the control, I did it using method pointer on a class base and every control inheriting from that one, I changed method pointer of the control to point to the windows method I wanted to call and everything worked well until I realize the every time a control call a method locate on the windows none of the data of the windows were available because of the This pointer pass was from the control not from the window as I wanted it to be

    Comment by Jman — July 26, 2011 @ 12:06 pm | Reply

  9. Thanks alot! Now my input system + camera system can finally start… I was procrastinating just due to this :P

    Comment by SnailCoder — August 6, 2011 @ 5:18 pm | Reply

  10. Thanks
    Works just fine.
    Avi

    Comment by Avi Manor — September 21, 2011 @ 2:07 pm | Reply

  11. An excellent article. I have a legacy PPC program and I was trying to flag when DB fields were null. This showed me how to do it, although in the end I succumbed to passing an interface pointer, using
    class IDoSomethingWithNullField
    {
    public:
    virtual void TagThatFieldIsNull() = 0;
    };

    Comment by brewmanz — July 2, 2012 @ 12:10 am | Reply

  12. My relatives all the time say that I am wasting my time here
    at net, except I know I am getting experience all the
    time by reading thes nice articles or reviews.

    Comment by Alina — May 20, 2013 @ 5:45 pm | Reply

  13. Great, thanks a million for this. Was getting frustrated trawling through Microsoft documentation trying to find the proper syntax – not something you keep in ready memory if not using it often. I Google’d it and found this brief and to-the-point explanation. Just excellent info, and now a respectful reference to you in my code comments :-) Thanks again.

    Comment by Søren L. Fog — October 16, 2013 @ 1:54 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: