Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling virtual functions through pointers with and without consulting the VM-table

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().

like image 481
bert-jan Avatar asked Nov 04 '22 18:11

bert-jan


1 Answers

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.

like image 148
Martin York Avatar answered Nov 12 '22 09:11

Martin York