5

I want to take the address of a member function of a c++ class, store it in a pointer, and call the virtual function later on.

I know some things about it, but do not now how to take the address of a certain implementation of a virtual function that is NOT the implementation of the most descendent class (the actual class of the object).

Here is some sample code:

    #include <iostream>

    using namespace std;

    class ca
    {
            public:
            virtual void vfunc() {cout << "a::vfunc ";}
            void mfunc() {cout << "a::mfunc ";}
    };

    class cb : public ca
    {
            public:
            virtual void vfunc() {cout << "b::vfunc ";}
    };

    extern "C" int main(int, char **)
    {
            void (ca:: *ptr_to_vfunc)() = &ca::vfunc;

            cout << sizeof(ptr_to_vfunc) << " ";

            cb b;

            (b.*ptr_to_vfunc)();

            ca a;

            (a.*ptr_to_vfunc)();

            void (ca:: *ptr_to_mfunc)() = &ca::mfunc;

            cout << sizeof(ptr_to_mfunc) << " ";
            (a.*ptr_to_mfunc)();
    }

The output is:

12 b::vfunc a::vfunc 12 a::mfunc

I am working with win32-environment, and the size of member function pointers is 3 * 32-bits values! I did not specify an object when I took the address of the member function and yet, my call invokes the most descendant class' implementation of vfunc().

1) What is going on here? Why 12 bytes in stead of 4? 2) How can I take the address of ca::vfunc() and call it on b, like I normaly would do with b.ca::vfunc().

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
bert-jan
  • 958
  • 4
  • 15
  • does `static_cast(&b)->vfunc()` work? – totowtwo Jul 12 '11 at 22:11
  • The call throught a member function pointer always calls the function pointed to by the corresponding entry in the virtual method table. Like someone answered below, you can not call b.ca::vfunc() through a pointer. Your call would invoke cb::vfunc() wether it is called throug a 'ca *' or a 'cb *' does not matter. What matters, is the actual type of the object. – bert-jan Jul 13 '11 at 08:03
  • Long read but possibly relevant: http://www.codeproject.com/KB/cpp/FastDelegate.aspx – cs95 Jul 19 '19 at 04:39
  • Long read, but [this article](http://www.codeproject.com/KB/cpp/FastDelegate.aspx) would answer it. – Ajay Jul 13 '11 at 15:07
  • Very long read indeed! I think, to call a member function at runtime, you need 4 things. (1)an object (2) the classes VM-table offset, (3) the offset withing te VMT, and , (4) if it's not a virtual function, you need an address of the member function. That explains why the size of the pointer is 3 machine words long. But I have one more question to @Ajay : Can you set up a member function pointer to call an implementation of a virtual function with no VM-table consulting? Code ample please. Thank you! (I did take a quick glance at the artical, but did not fully read it). – bert-jan Jul 13 '11 at 15:39

1 Answers1

2

Ok: Its doing exactly what it it is supposed to do.

But to answer you questions:

1) What is going on here? Why 12 bytes in stead of 4?

Why not.
The standard does not specify a size.
I am not sure why you expect a normal pointer to be 4.

If the question is "why is a method pointer larger than a normal pointer?"

Because the implementation needs the extra space to hold information about the call.

2) How can I take the address of ca::vfunc() and call it on b, like I normaly would do with b.ca::vfunc().

You cant.

Martin York
  • 257,169
  • 86
  • 333
  • 562