Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't C++ have a pointer to member function type?

I could be totally wrong here, but as I understand it, C++ doesn't really have a native "pointer to member function" type. I know you can do tricks with Boost and mem_fun etc. But why did the designers of C++ decide not to have a 64-bit pointer containing a pointer to the function and a pointer to the object, for example?

What I mean specifically is a pointer to a member function of a particular object of unknown type. I.E. something you can use for a callback. This would be a type which contains two values. The first value being a pointer to the function, and the second value being a pointer to the specific instance of the object.

What I do not mean is a pointer to a general member function of a class. E.G.

int (Fred::*)(char,float)

It would have been so useful and made my life easier.

Hugo

like image 791
Rocketmagnet Avatar asked Jan 20 '09 17:01

Rocketmagnet


People also ask

Can we create a pointer to a member function?

You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.

Can we have a pointer to a function in C?

In C, like normal data pointers (int *, char *, etc), we can have pointers to functions. Following is a simple example that shows declaration and function call using function pointer.

Which member function do not get this pointer?

The this pointer is a pointer accessible only within the nonstatic member functions of a class , struct , or union type. It points to the object for which the member function is called. Static member functions don't have a this pointer.

How member functions can be accessed using pointers?

To access a member function by pointer, we have to declare a pointer to the object and initialize it (by creating the memory at runtime, yes! We can use new keyboard for this). The second step, use arrow operator -> to access the member function using the pointer to the object.


1 Answers

@RocketMagnet - This is in response to your other question, the one which was labeled a duplicate. I'm answering that question, not this one.

In general, C++ pointer to member functions can't portably be cast across the class hierarchy. That said you can often get away with it. For instance:

#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};

int main() {
    typedef void (A::*pmf_t)();
    C c; c.x = 42; c.y = -1;

    pmf_t mf = static_cast<pmf_t>(&C::foo);
    (c.*mf)();
}

Compile this code, and the compiler rightly complains:

$ cl /EHsc /Zi /nologo pmf.cpp
pmf.cpp
pmf.cpp(15) : warning C4407: cast between different pointer to member representations, compiler may generate incorrect code

$

So to answer "why doesn't C++ have a pointer-to-member-function-on-void-class?" is that this imaginary base-class-of-everything has no members, so there's no value you could safely assign to it! "void (C::)()" and "void (void::)()" are mutually incompatible types.

Now, I bet you're thinking "wait, i've cast member-function-pointers just fine before!" Yes, you may have, using reinterpret_cast and single inheritance. This is in the same category of other reinterpret casts:

#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};
class D { public: int z; };

int main() {
    C c; c.x = 42; c.y = -1;

    // this will print -1
    D& d = reinterpret_cast<D&>(c);
    cout << "d.z == " << d.z << "\n";
}

So if void (void::*)() did exist, but there is nothing you could safely/portably assign to it.

Traditionally, you use functions of signature void (*)(void*) anywhere you'd thing of using void (void::*)(), because while member-function-pointers don't cast well up and down the inheritance heirarchy, void pointers do cast well. Instead:

#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};

void do_foo(void* ptrToC){
    C* c = static_cast<C*>(ptrToC);
    c->foo();
}

int main() {
    typedef void (*pf_t)(void*);
    C c; c.x = 42; c.y = -1;

    pf_t f = do_foo;
    f(&c);
}

So to your question. Why doesn't C++ support this sort of casting. Pointer-to-member-function types already have to deal with virtual vs non-virtual base classes, and virtual vs non-virtual member functions, all in the same type, inflating them to 4*sizeof(void*) on some platforms. I think because it would further complicate the implementation of pointer-to-member-function, and raw function pointers already solve this problem so well.

Like others have commented, C++ gives library writers enough tools to get this done, and then 'normal' programmers like you and me should use those libraries instead of sweating these details.

EDIT: marked community wiki. Please only edit to include relevant references to the C++ standard, and add in italic. (esp. add references to standard where my understanding was wrong! ^_^ )

like image 200
4 revs, 2 users 99% Avatar answered Oct 03 '22 07:10

4 revs, 2 users 99%