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.
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.
Calling a Function Through a Function Pointer in Cusing function pointer (a) int area = (*pointer)(length); // 3. using function pointer (b) int area = pointer(length);
the constructor is the first function which get called. and we can access the this pointer via constructor for the first time. if we are able to get the this pointer before constructor call (may be via malloc which will not call constructor at all), we can call member function even before constructor call.
Read this for detail :
// 1 define a function pointer and initialize to NULL
int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL;
// C++
class TMyClass
{
public:
int DoIt(float a, char b, char c){ cout << "TMyClass::DoIt"<< endl; return a+b+c;};
int DoMore(float a, char b, char c) const
{ cout << "TMyClass::DoMore" << endl; return a-b+c; };
/* more of TMyClass */
};
pt2ConstMember = &TMyClass::DoIt; // note: <pt2Member> may also legally point to &DoMore
// Calling Function using Function Pointer
(*this.*pt2ConstMember)(12, 'a', 'b');
How do I obtain a function pointer for a class member function, and later call that member function with a specific object?
It's easiest to start with a typedef
. For a member function, you add the classname in the type declaration:
typedef void(Dog::*BarkFunction)(void);
Then to invoke the method, you use the ->*
operator:
(pDog->*pBark)();
Also, if possible, I’d like to invoke the constructor via a pointer as well. Is this possible, and if so, what is the preferred way to do this?
I don't believe you can work with constructors like this - ctors and dtors are special. The normal way to achieve that sort of thing would be using a factory method, which is basically just a static function that calls the constructor for you. See the code below for an example.
I have modified your code to do basically what you describe. There's some caveats below.
#include <iostream>
class Animal
{
public:
typedef Animal*(*NewAnimalFunction)(void);
virtual void makeNoise()
{
std::cout << "M00f!" << std::endl;
}
};
class Dog : public Animal
{
public:
typedef void(Dog::*BarkFunction)(void);
typedef Dog*(*NewDogFunction)(void);
Dog () {}
static Dog* newDog()
{
return new Dog;
}
virtual void makeNoise ()
{
std::cout << "Woof!" << std::endl;
}
};
int main(int argc, char* argv[])
{
// Call member function via method pointer
Dog* pDog = new Dog ();
Dog::BarkFunction pBark = &Dog::makeNoise;
(pDog->*pBark)();
// Construct instance via factory method
Dog::NewDogFunction pNew = &Dog::newDog;
Animal* pAnimal = (*pNew)();
pAnimal->makeNoise();
return 0;
}
Now although you can normally use a Dog*
in the place of an Animal*
thanks to the magic of polymorphism, the type of a function pointer does not follow the lookup rules of class hierarchy. So an Animal method pointer is not compatible with a Dog method pointer, in other words you can't assign a Dog* (*)()
to a variable of type Animal* (*)()
.
The static newDog
method is a simple example of a factory, which simply creates and returns new instances. Being a static function, it has a regular typedef
(with no class qualifier).
Having answered the above, I do wonder if there's not a better way of achieving what you need. There's a few specific scenarios where you would do this sort of thing, but you might find there's other patterns that work better for your problem. If you describe in more general terms what you are trying to achieve, the hive-mind may prove even more useful!
Related to the above, you will no doubt find the Boost bind library and other related modules very useful.
I don't think anyone has explained here that one issue is that you need "member pointers" rather than normal function pointers.
Member pointers to functions are not simply function pointers. In implementation terms, the compiler cannot use a simple function address because, in general, you don't know the address to call until you know which object to dereference for (think virtual functions). You also need to know the object in order to provide the this
implicit parameter, of course.
Having said that you need them, now I'll say that you really need to avoid them. Seriously, member pointers are a pain. It is much more sane to look at object-oriented design patterns that achieve the same goal, or to use a boost::function
or whatever as mentioned above - assuming you get to make that choice, that is.
If you are supplying that function pointer to existing code, so you really need a simple function pointer, you should write a function as a static member of the class. A static member function doesn't understand this
, so you'll need to pass the object in as an explicit parameter. There was once a not-that-unusual idiom along these lines for working with old C code that needs function pointers
class myclass
{
public:
virtual void myrealmethod () = 0;
static void myfunction (myclass *p);
}
void myclass::myfunction (myclass *p)
{
p->myrealmethod ();
}
Since myfunction
is really just a normal function (scope issues aside), a function pointer can be found in the normal C way.
EDIT - this kind of method is called a "class method" or a "static member function". The main difference from a non-member function is that, if you reference it from outside the class, you must specify the scope using the ::
scope resolution operator. For example, to get the function pointer, use &myclass::myfunction
and to call it use myclass::myfunction (arg);
.
This kind of thing is fairly common when using the old Win32 APIs, which were originally designed for C rather than C++. Of course in that case, the parameter is normally LPARAM or similar rather than a pointer, and some casting is needed.
typedef void (Dog::*memfun)();
memfun doSomething = &Dog::bark;
....
(pDog->*doSomething)(); // if pDog is a pointer
// (pDog.*doSomething)(); // if pDog is a reference
Minimal runnable example
main.cpp
#include <cassert>
class C {
public:
int i;
C(int i) : i(i) {}
int m(int j) { return this->i + j; }
};
int main() {
// Get a method pointer.
int (C::*p)(int) = &C::m;
// Create a test object.
C c(1);
C *cp = &c;
// Operator .*
assert((c.*p)(2) == 3);
// Operator ->*
assert((cp->*p)(2) == 3);
}
Compile and run:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Tested in Ubuntu 18.04.
You cannot change the order of the parenthesis or omit them. The following do not work:
c.*p(2)
c.*(p)(2)
GCC 9.2 would fail with:
main.cpp: In function ‘int main()’:
main.cpp:19:18: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘p (...)’, e.g. ‘(... ->* p) (...)’
19 | assert(c.*p(2) == 3);
|
C++11 standard
.*
and ->*
are a single operators introduced in C++ for this purpose, and not present in C.
C++11 N3337 standard draft:
.*
and ->*
.I came here to learn how to create a function pointer (not a method pointer) from a method but none of the answers here provide a solution. Here is what I came up with:
template <class T> struct MethodHelper;
template <class C, class Ret, class... Args> struct MethodHelper<Ret (C::*)(Args...)> {
using T = Ret (C::*)(Args...);
template <T m> static Ret call(C* object, Args... args) {
return (object->*m)(args...);
}
};
#define METHOD_FP(m) MethodHelper<decltype(m)>::call<m>
So for your example you would now do:
Dog dog;
using BarkFunction = void (*)(Dog*);
BarkFunction bark = METHOD_FP(&Dog::bark);
(*bark)(&dog); // or simply bark(&dog)
Edit:
Using C++17, there is an even better solution:
template <auto m> struct MethodHelper;
template <class C, class Ret, class... Args, Ret (C::*m)(Args...)> struct MethodHelper<m> {
static Ret call(C* object, Args... args) {
return (object->*m)(args...);
}
};
which can be used directly without the macro:
Dog dog;
using BarkFunction = void (*)(Dog*);
BarkFunction bark = MethodHelper<&Dog::bark>::call;
(*bark)(&dog); // or simply bark(&dog)
For methods with modifiers like const
you might need some more specializations like:
template <class C, class Ret, class... Args, Ret (C::*m)(Args...) const> struct MethodHelper<m> {
static Ret call(const C* object, Args... args) {
return (object->*m)(args...);
}
};
A function pointer to a class member is a problem that is really suited to using boost::function. Small example:
#include <boost/function.hpp>
#include <iostream>
class Dog
{
public:
Dog (int i) : tmp(i) {}
void bark ()
{
std::cout << "woof: " << tmp << std::endl;
}
private:
int tmp;
};
int main()
{
Dog* pDog1 = new Dog (1);
Dog* pDog2 = new Dog (2);
//BarkFunction pBark = &Dog::bark;
boost::function<void (Dog*)> f1 = &Dog::bark;
f1(pDog1);
f1(pDog2);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With