C++ Class Member Function Pointer to Function Pointer

Calling C++ member functions via a function pointer

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');

Assign C++ member function to C function pointer

You simply cannot do this. Member functions have an implicit this argument that is a pointer to the object on which the function is being called. A function that does not take a B* as an argument will never manage to run on a specific B instance and a function that does not take this point as its first argument can never have the same signature as a class method. For more details on this problem and an example of a workaround read:

https://isocpp.org/wiki/faq/pointers-to-members#memfnptr-vs-fnptr

Pay attention to the note at the bottom of the answer on how static member functions can be used in such manner.

Pure C++ projects can use std::function & std::bind to achieve what you are asking about, but a C library used by a C++ project cannot work with these types.

C++ How to make function pointer to class method

A member function is quite a bit different from an ordinary function, so when you want to point to a member function you need a pointer-to-member-function, not a mere pointer-to-function. The syntax for a pointer-to-member-function includes the class that the member function is a member of:

void (Game::*mptr)();

This defines a pointer-to-member-function named mptr that holds a pointer to a member function of the class Games that takes no arguments and returns nothing. Contrast that with an ordinary function pointer:

void (*ptr)();

This defined a pointer-to-function named ptr that holds a pointer to a function that takes no arguments and returns nothing.

Assign function pointer inside class

Pointers to function and pointers to member functions are different things.
You need an object to call a member function.

A pointer to a meber function can be declared like this:

void (ClassB::*ptrPtrintFunc)(int) = &ClassB::printFun;

And you can call it like this:

ClassB classB;
(classB.*ptrPtrintFunc)(1);

or this:

ClassB *ptrClassB = &classB;
(ptrClassB->*ptrPtrintFunc)(2);

What you can do ist to use std::function instead a of the old school function pointer.
You can pass a lambda function to the std::function, in which you call the method of the class:

#include <iostream>
#include <functional> // std::function

struct ClassA
{
using TFunc = std::function<void( int )>; // <-- std::function<void( int )> insted of void(*)(int)
ClassA( TFunc func) : funPtr( func ) {}
TFunc funPtr;
};

struct ClassB
{
void printFun( int a ) { std::cout << a << std::endl; }
};

int main()
{
ClassB classB;
ClassA classA( [&classB]( int a ) { classB.printFun(a); } ); // <-- lambda function
classA.funPtr(5);
return 0;
}

Instead of the lambda function, you can also use std::bind with a std::placholder for the parameter:

ClassB classB;
ClassA classA( std::bind( &ClassB::printFun, &classB, std::placeholders::_1 ) );
classA.funPtr(5);

Of course you can also pass a simple function to std::function

void printFunc( int a ) { std::cout << a << std::endl; }

ClassA classA( printFunc );

Extension to the answer : Solution without using STL

Thanks for the information. I am using std library to print in the experimenting code. But the actual code I am writing is in kernel mode, so I will not have access to std library. I wonder if there is another way to do this.

If you don't want to use STL anyway you can think about a solution with an abstract base class.
You need a base class with an abstract callback method and you need 2 derived classes which overrides the abstract callback method. The implementations of the callback methods delegate the callback either to a function or to class method.

Abstract class with the abstract methode CallBack:

struct CCallBack
{
virtual void CallBack( int ) = 0;
};

Implementation for a function pointer. The overridden method CallBack delegates the callback to a function pointer:

struct CCallBackFunc : public CCallBack
{
typedef void(*TFuncPtr)(int);
TFuncPtr _funcPtr;
CCallBackFunc( TFuncPtr funcPtr ) : _funcPtr( funcPtr ) {}
virtual void CallBack( int a ) override { (*_funcPtr)( a ); }
};

Implementation for a method function pointer. The overridden method CallBack delegates the callback to an
object and a method function pointer:

template < class T >
struct CCallBackMethod : public CCallBack
{
typedef void(T::*TMethodPtr)(int);
T &_obj;
TMethodPtr _methodPtr;
CCallBackMethod( T &obj, TMethodPtr methodePtr ) : _obj( obj ), _methodPtr( methodePtr ) {}
virtual void CallBack( int a ) override { (_obj.*_methodPtr)( a ); }
};

Example for the use of both cases:

struct ClassA
{
ClassA( CCallBack *cb ) : _cb( cb ) {}
virtual ~ClassA() { delete _cb; }
CCallBack *_cb;
};

struct ClassB { void printFun( int a ) { std::cout << a << std::endl; } };
void printFun( int a ) { std::cout << a << std::endl; }

int main()
{
ClassB classB;
ClassA classA0( new CCallBackFunc( &printFun ) );
ClassA classA1( new CCallBackMethod<ClassB>( classB, &ClassB::printFun ) );
classA0._cb->CallBack( 6 );
classA1._cb->CallBack( 7 );
return 0;
}

Difficulty in passing function pointer of a class member function

You can't pass a non-static member function pointer as a regular function pointer. Member functions have access to the this pointer, and the way they get that is via an invisible implicit function parameter. You need to have the object on which to call the function, and the function itself, be bound together, which a function pointer simply can't do.

What we can do is make print_array_of_length5 a function template, and allow it to take any type of callable. That would give you something like this:

template <typename Function>
void print_array_of_length5(Function func){
for (int i = 0; i < 5; i++)
printf("%d ", func(i));
}

To call it with a non-static member function, you can use a lambda expression, or std::bind(), like this:

SIMPLE smpl;
print_array_of_length5([&smpl](int foo){ return smpl.retval(foo); });
using namespace std::placeholders;
SIMPLE smpl;
auto func = std::bind(&SIMPLE::retval, &smpl, _1);
print_array_of_length5(func);

Class member function pointer

If the function is not static, you cannot pass it in input to a function that accepts a non-member function pointer.

Consider that a non-static member function has an implicit pointer to ClassName as its first parameter, which points to the object on which the member function is being invoked.

struct X
{
static void foo() { } // Does not have an implicit "this" pointer argument
void bar() { } // Has an implicit "this" pointer argument
};

int main()
{
void (*f)() = &X::foo; // OK: foo is static
void (*g)() = &X::bar; // ERROR! bar is non-static
}

Here, not even std::bind() will work, because the result is not convertible to a function pointer. Lambdas are convertible to function pointers, but only if they are non-capturing (and a lambda here would need to capture the object to invoke the member function on).

Therefore, the only (ugly) workaround is to have a global adapter function which invokes the member function on an object which is available through a global pointer variable. The global pointer variable is set prior to calling the function:

struct X
{
void bar() { }
};

void function_taking_a_function_pointer(void (*f)())
{
// Do something...
f();
}

X* pX = nullptr;
void bar_adapter()
{
pX->bar();
}

int main()
{
X x; // Some object I want to invoke the member function bar() on...

pX = &x; // Set the global pointer and invoke the function...
function_taking_a_function_pointer(bar_adapter);
}

If you want, you can make this slightly more flexible by turning bar_adapter into a function template, and passing the pointer-to-member-function as a template argument:

template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}

Here is how you would use it:

#include <iostream>

struct X
{
void foo() { std::cout << "X::foo()" << std::endl; }
void bar() { std::cout << "X::bar()" << std::endl; }
};

void function_taking_a_function_pointer(void (*f)())
{
// Do something...
f();
}

X* pX = nullptr;

template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}

int main()
{
X x; // Some object I want to invoke the member function bar() on...

pX = &x; // Set the global pointer and invoke the function(s)...

function_taking_a_function_pointer(adapter<X, &X::foo>);
function_taking_a_function_pointer(adapter<X, &X::bar>);
}

Finally, here is a live example.

assign a member function to a function pointer

Your code looks confusing and, personally, I believe that C function pointers look ugly on C++'s OO implementation. So I would advise you to use the std::function. It only has been available since C++11. If you cannot use it, try looking on Boost's Implementation.

I can give you an example of how to use the std::function:

bool MyFunction(int i)
{
return i > 0;
}

std::function<bool(int)> funcPointer = MyFunction;

Using this you will drastically improve your code reliability. As of your problem, specifically:

class A
{
public:
std::function<int*(const int&)> fun;
A(std::function<int*(const int&)> f) : fun(f) {}
};

class B
{
private:
float r;
int *f(const int &t)
{
return new int(int(r) + t);
}
A *a;
B()
{

std::function<int*(const int&)> tempFun = std::bind(&B::f, this, _1);
a = new A(tempFun);
}
};

You have to add the following namespace:

using namespace std::placeholders;

C++ class member function pointer to function pointer

No. A member function is not a free function. The type is entirely different, and a pointer to a member function (PTMF) is a completely different, incompatible object from a function pointer. (A PTMF is usually much bigger, for example.) Most importantly a pointer-to-member must always be used together with an instance pointer to the object whose member you want to call, so you cannot even use a PTMF the same way you use a function pointer.

The easiest solution for interacting with C code is to write a global wrapper function that dispatches your call, or to make your member function static (in which case it becomes essentially a free function):

// global!

Engine * myEngine;
int theCallback(lua_State * L)
{
return myEngine->pcall_log(L);
}

Engine::Run()
{
/* ... */
myEngine = this;
luabind::set_pcall_callback(&theCallback);
/* ... */
}

The conceptual problem here is that you have an engine class, although you will practically only have one single instance of it. For a genuine class with many objects, a PTMF wouldn't make sense because you'd have to specify which object to use for the call, whereas your engine class perhaps is essentially a singleton class which could be entirely static (i.e. a glorified namespace).

Use pointer to member function to determine which function to call

Syntax to call a member function via member function pointer is

(this->*memf)();

You cannot magically turn the string into a member function pointer. Sloppy speaking, names of functions do not exist at runtime. If you want such mapping you need to provide it yourself. No way around that. What you can avoid is the "forest of if-else" by using a std::unordered_map:

#include <unordered_map>
#include <string>
#include <iostream>

class Karen
{
public:
void complain(std::string level) {
static const std::unordered_map<std::string, void(Karen::*)() const> m{
{"debug",&Karen::debug},
{"info",&Karen::info},
{"warning",&Karen::warning},
{"error",&Karen::error}
};
auto it = m.find(level);
if (it == m.end()) return;
(this->*(it->second))();
}

private:
void debug(void) const { std::cout << "debug\n"; }
void info(void) const { std::cout << "info\n"; }
void warning(void) const { std::cout << "warning\n"; }
void error(void) const { std::cout << "error\n"; }
};

int main() {
Karen k;
k.complain("info");
}

Live Demo

As mentioned in comments, you could use an enum in place of the string. When possible you should use the help of the compiler, which can diagnose a typo in an enum but not in a string. Alternatively you could directly pass a member function pointer to complain. Then implementation of complain would be trivial, no branching needed. Though this would require the methods to be public and the caller would have to deal with member function pointers.


If you are not allowed to use C++11 or newer you should have a serious talk with your teacher. Soon C++20 will be the de facto standard and things have changed quite a lot. I am not fluent in C++98 anymore, so here is just a quick fix of the above to get it working somehow. You cannot use std::unordered_map but there is std::map and initialization of the map is rather cumbersome:

#include <map>
#include <string>
#include <iostream>

class Karen
{
typedef void(Karen::*memf_t)() const;
typedef std::map<std::string,void(Karen::*)() const> map_t;

public:
void complain(std::string level) {
map_t::const_iterator it = get_map().find(level);
if (it == get_map().end()) return;
(this->*(it->second))();
}

private:
const map_t& get_map(){
static const map_t m = construct_map();
return m;
}
const map_t construct_map() {
map_t m;
m["debug"] = &Karen::debug;
m["info"] = &Karen::info;
m["warning"] = &Karen::warning;
m["error"] = &Karen::error;
return m;
}
void debug(void) const { std::cout << "debug\n"; }
void info(void) const { std::cout << "info\n"; }
void warning(void) const { std::cout << "warning\n"; }
void error(void) const { std::cout << "error\n"; }
};

int main() {
Karen k;
k.complain("info");
}

Live Demo



Related Topics



Leave a reply



Submit