Below method of calling D::foo
function via pointer-to-member function will generate error: must use .*
or ->*
to call pointer-to-member function in 'f (...)'
.. of course that is not how we call pointer-to-member functions.
The correct way of calling is (d.*f)(5);
OR (p->*f)(5);
My question is, 'Is there a way to call member function of a class without the class object on left hand side? I wonder if we could pass class object (this
) as regular argument?
In my mind, at end of the day (at assembly/binary level) all member functions of a class are normal functions which should operate on n + 1 arguments where (+1 is for this
)
If we talk about D::foo
function below, at assembly/binary level it should operate on two arguments:
- The class object itself (pointer to class D object called
this
) - and the
int
.
so, is there a way (or hack) to call D::foo
with class object passed to it as function argument instead of using . or -> or .* or ->*
operators on class object?
Sample Code:
#include <iostream>
using namespace std;
class D {
public:
void foo ( int a ) {
cout << "D" << endl;
}
int data;
};
//typedef void __cdecl ( D::* Func)(int);
typedef void ( D::* Func)(int);
int main ( void )
{
D d;
Func f = &D::foo;
f(&d, 5);
return 1;
}
One method is using boost bind i.e
(boost:: bind (&D::foo, &d, 5)) ();
EDIT: "Please note I am not looking for a version of this program which works, I know how to make it work"
Although I think its a kind of strange thing to want, call_member looks like what you want. (Needs C++11)
Two ways without assembly:
Yes, there is an abstraction in the C++11 standard called INVOKE which applies to Callable objects. Pointer-to-member-function (PTMF) objects are Callable and
this
is passed as the first (regular) argument.There is no
std::invoke
function, although it has been proposed. To get a functor from any Callable object, you can usestd::bind
, which is a derivative of Boost.bind.This works fine:
http://ideone.com/VPWV5U
In short, no. You cannot call a non-
static
class member function without somehow specifying the object on the left side of the call. If the class (for static functions) or the object (for non-static) is not specified, the compiler has no way of knowing which function you are trying to call. It's outside the current scope because it's inside a class or object. There are ways to "hack" code so you can write it to look likemain()
in your example. Some of the other answers give examples of just these kinds of hacks.------------Using static functions-----------------
A function within a class can be called outside the class without specifying a class object. The way to do it is to create a
typedef
for a function pointer with a signature that matches the class function's, then creating such a pointer and assigning it the address of the class function. That function can then be called without needing to specify the class or an object on the left side.The function must be
static
. ISO C++ does not allow taking the address of a bound member function to form a pointer to that function, i.e. you cannot create a pointer to a non-static
member function from a class object. You may be able to find some non-ISO standard compliant compilers, but I don't have any guidance on that for you.The parameter
this
to non-static
class member functions is an implied parameter, and is always an implied parameter. You cannot manually specify it, but you can emulate it by passing a pointer to an object of the class.So, for your code example:
void D::foo(int)
should bestatic
and have an addedD*
parameter:class D { static void D::foo(D*, int); };
.typedef void (D::* Func)(int);
should be changed to accommodate the previous change and removeD::
:typedef void (*Func)(D*, int);
Yes, it is true that with enough contortions you can evade the "new" member function syntax, but I have to ask: why would you? The syntax fosters the understanding that the member function is somehow invoked from the surrounding object. Given the existence of virtual functions this is actually (and must be) the case. It also automates the this pointer changes the calling of virtual functions (and support for virtual inheritance) requires.
For an illustration of how you can go about doing this look at the implementation of the FastDelegate library. It's implementation is required to know the binary structure of your compiler's member function pointers (of which there can be several varieties). That's the "hack" you're looking for. FastDelegate's delegates (ie closures) turn into two instructions at the call point: pulling the computed 'this' value into the proper place (based on calling convention) and indirectly jumping to the actual function's entry address.
This ends up looking like this:
This is pretty similar to what boost::bind and friends are doing, but is generally faster (though, clearly, less portable).
Underneath the templates and operator overloading used here there's some math (inside the bind function) which figures out how to alter &someInstance into the this pointer needed by SomeClass::someInstance. It also finds the actual address of the underlying function and records both values for later. When the call takes place it forces the compiler to "do the right thing" by some trickery using
->*
. But, if you really wanted to avoid even relying on the->*
operator you could, at that point, do some type casts and turn the pointer into a "__thiscall" function pointer (well, assuming you are on Windows):So, what was it exactly you didn't like about: someInstance->someFunction()?
I'm not quite sure what you're asking. There is no "artificial restriction" on calling functions via pointers to members; you just have to use the correct syntax:
bind
doesn't do any "magic"; somewhere in its implementation, it does exactly that.No, it's a member function that takes one argument, and is called on an object. While conceptually similar to a function taking two arguments, there is one big difference: member functions can be virtual, involving a run-time dispatch mechanism.