C++ How to make function pointer to class method [duplicate] - c++

This question already has answers here:
Calling C++ member functions via a function pointer
(10 answers)
Closed 9 months ago.
I'm having trouble making a function pointer to a class method. I made a function pointer to a non-class method and it works fine.
int foo(){
return 5;
}
int main()
{
int (*pointer)() = foo;
std::cout << pointer();
return 0;
}
I tried to apply this to have an instance variable in a class be a function pointer.
This is the header file. It declares the private method Print which the variable method will point to.
class Game
{
public:
Game();
private:
void Print();
void (method)( void );
};
The Game constructor attempts to assign the pointer method to the address of the Print method. Upon compile, an error comes up at that line saying "error: reference to non-static member function must be called;". I don't know what that means. Whats the correct way of implementing this?
Game::Game( void )
{
method = &Game::Print;
}
void Game::Print(){
std::cout << "PRINT";
}

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.

Just found out you can do
#include <functional>
#include <cassert>
using namespace std;
struct Foo {
int x;
int foo() { return x; }
};
int main() {
function<int(Foo&)> f = &Foo::foo;
Foo foo = { 3 };
assert(f(foo) == 3);
foo.x = 5;
assert(f(foo) == 5);
}
std::mem_fn() might work too: https://en.cppreference.com/w/cpp/utility/functional/mem_fn

1- Use the following syntax to point to a member function:
return_type (class_name::*ptr_name) (argument_type) = &class_name::function_name;
2- keep in mind to have a pointer to member function you need to make it public.
in your case:
class Game
{
public:
Game(){}
void print() {
//todo ...
}
};
// Declaration and assignment
void (Game::*method_ptr) () = &Game::print;

Related

Call a pointer-to-function outside the structure

I have a structure, inside it a pointer to function from the same structure. And now I need to call a pointer to function outside the structure. I give an example of the code below:
#include <iostream>
struct test {
void (test::*tp)(); // I need to call this pointer-to-function
void t() {
std::cout << "test\n";
}
void init() {
tp = &test::t;
}
void print() {
(this->*tp)();
}
};
void (test::*tp)();
int main() {
test t;
t.init();
t.print();
(t.*tp)(); // segfault, I need to call it
return 0;
}
(t.*tp)(); is trying to invoke the member function pointer tp which is defined at global namespace as void (test::*tp)();, note that it's initialized as null pointer in fact (via zero initialization1), invoking it leads to UB, anything is possible.
If you want to invoke the data member tp of t (i.e., t.tp) on the object t, you should change it to
(t.*(t.tp))();
^
|
---- object on which the member function pointed by tp is called
If you do want to invoke the global tp, you should initialize it appropriately, such as
void (test::*tp)() = &test::t;
then you can
(t.*tp)(); // invoke global tp on the object t
1 About zero initialization
Zero initialization is performed in the following situations:
1) For every named variable with static or thread-local storage duration that is not subject to constant initialization (since C++14), before any other initialization.
#songyuanyao's answer is valid. However, are you sure you want to use your structure that way? Why not just use inheritance and virtual methods? :
class base_test {
public:
virtual void t() { std::cout << "test\n"; }
void print() { t(); }
};
and then you can subclass it:
class my_test : base_test {
public:
virtual void t() { std::cout << "my test\n"; }
};
In your main() function (or wherever) you could have functions returning pointers or references to the base class, which are actually instances of subclasses. And this way, you don't have to worry about pointers.
The downside is that you have to know about your different tests at compile time (and then not even at the site of use, as I just explained). If you do, I'd go with the common idiom.

Function pointer of a member function of the current instance

I want to get the function pointer of a member function of the current instance of a C++ class. Then I want to add that function pointer to a global registry.
I can't create the instance in a separate location and add the function pointer there. It should get added within this instance.
This is what I have done. But it doesn't work as intended. Is there anything I am doing wrong here?
Example
In MyClass.h
class MyClass
{
public:
MyClass();
~MyClass();
typedef int (MyClass::*fpointer)(int);
int foo(int val);
private:
void addFuncPointer();
}
In MyClass.cpp
MyClass::MyClass()
{
addFuncPointer();
}
int MyClass::foo(int val)
{
// Function Definition
}
void MyClass::addFuncPointer()
{
fpointer funct = &MyClass::foo;
//I am adding this function pointer to a global registry.
GlobalRegistry.add(globalindex, funct);
globalindex++;
}
In Main.cpp
int main()
{
MyClass* cls = new MyClass();
GlobalRegistry.getFunctionPointer(validindex)->call();
return 0;
}
The problem that you are experiencing is caused by the fact that all objects of a class share the same code for their member functions. So if you want to invoke a member function for a particular instance, you're gonna need to save both, a pointer to the instance and a pointer to the member function.
Since C++11 this can be wrapped into a function object:
struct Foo {
void func() { /* ... */ }
} foo;
auto mem_func = std::bind(&Foo::func, &foo);
mem_func();

Passing any generic function as a C++ argument [duplicate]

This question already has answers here:
Function pointer to member function
(8 answers)
Closed 8 years ago.
I'm trying to pass any generic function as an argument in a C++ function. As an extra layer of fun, the function is going to reside in its own separate class. In this particular case, they will all take no arguments and return void. This includes members of any generic class.
My current code reads like:
class functionsFedHere {
public:
void (*callback)();
functionsFedHere(void(*)());
}
functionsFedHere::functionsFedHere (void(*callbackFunction)()) {
callback = callbackFunction;
}
void fn1() { cout<<"Fn1"<<endl; }
class myClass {
public:
int i;
void fn2() { cout<<i<<endl; }
}
class myOtherClass {
public:
string j;
void fn3() { cout<<j<<endl; }
}
int main() {
// Initialise some objects
myClass b;
b.i = 2;
myOtherClass c;
c.j = "some text";
// Works fine with non-member functions
functionsFedHere objectA(fn1);
objectA.callback();
// Doesn't work with member functions
functionsFedHere objectB(b.fn2);
functionsFedHere objectC(c.fn3);
}
I've seen solutions like a forwarding function, or boost::bind, but as far as I can tell, I don't think these solutions will fit?
It's also worth noting that eventually I'd like to pass member functions by way of an array of pointers. For example, if myPointer[] is an array of pointers to objects of class myClass, then it would be nice to be able to write something like:
functionsFedHere objectD(myPointer[0]->fn2);
EDIT: Apparently I wasn't clear enough. This answer is not an appropriate answer, because I'm looking to pass both member and non-member functions as arguments (whereas the suggested answer is setting up a member pointer to a function that is a member of the same class).
I don't think that the forward function example will work, because the forwarding function assumes a single class type, where I'd like to pass an object of generic class.
boost::bind could well be the answer; I'm just unfamiliar with it. Can anyone point me towards some newbie-friendly reading material?
EDIT 2: Sorry, forgot to mention I'm programming on a device that is pre-C++11.
Use std::function:
class functionsFedHere {
public:
typedef std::function<void()> Func;
Func callback;
functionsFedHere(Func callback_) : callback(callback_) {}
};
void fn1() { cout<<"Fn1"<<endl; }
class myClass {
public:
int i;
void fn2() { cout<<i<<endl; }
};
class myOtherClass {
public:
string j;
void fn3() { cout<<j<<endl; }
};
class callableClass {
public:
void operator()() { std::cout << "in callableClass" << std::endl; }
};
int main() {
// Initialise some objects
myClass b;
b.i = 2;
myOtherClass c;
c.j = "some text";
// Works fine with non-member functions
functionsFedHere objectA(fn1);
objectA.callback();
// Works with member functions now
functionsFedHere objectB(std::bind(&myClass::fn2, b));
objectB.callback();
functionsFedHere objectC(std::bind(&myOtherClass::fn3, c));
objectC.callback();
// Works with lambdas as well
functionsFedHere objectLambda([]() { std::cout << "in lambda" << std::endl; });
objectLambda.callback();
// Works also with classes with overloaded operator()
functionsFedHere(callableClass()).callback();
return 0;
}

Function pointer in class A to member function from class B

I'm searching a solution for this for a few days now. Didn't find any question related enough to answer regrettably so here is my question.
Consider the next code:
// dummy class A
class A {
public:
void aFunction() { // <- this is the function I want to point at
cout << "aFunction() is called\n";
}
};
class B {
public:
template <class Class> // get a function pointer
void setFunction( void (Class::*func)() ) {
p_func = func;
}
void (*p_func)(); // the function pointer
}
int main() {
B obj;
objb.setFunction(&A::aFunction);
return 0;
}
I have a compilation error in setFunction() on p_func = func;:
cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'
And I don't seem to be able to get rid of it in any way. I know it has something to do with those invisible this pointers (__thiscall and __cdecl), but I don't know how to handle these. I tried making the member variable p_func a class template too (void (Class::*p_func)()) so it would have the same structure, but it that seems to be illegal to have 2 class templates in one class (why?), thus isn't the correct solution. This time the compiler complains about:
multiple template parameter lists are not allowed
This method (without the template) works perfectly on global functions (which is the workaround I currently use) and I saw the use of it in a library (sfgui), so it should be perfectly possible.
To have some context over why I'd want this: I'm trying to create a button. This button should be able to call whatever function I'd like. For now, I'd like it to call the start() function of an animation class I'm making.
p.s.: I know this example is useless since I can't run p_func: the function isn't static. I still need to add an object pointer (setFunction( void (Class::*func)(), Class* )), but that does not seem to be a problem. And I know about typedef to make a function pointer more readable, but not with a class template.
EDIT
After some more research I think the answer I need not the answer to this question, but rather another one. For once, I noticed that multiple template <class Class> is in fact allowed. However, it is not allowed on member variables since the compiler can't possibly know which class he'll need to use which probably is the reason for the error
multiple template parameter lists are not allowed
which is an odd description. Thanks anyway for the help, you did gave me a better insight.
You cannot convert a pointer-to-member Class::*func to a normal function pointer. They are of different types.
You should turn this:
void (*p_func)(); // the function pointer
into this:
void (class::*p_func)(); // the function pointer
You could also use a std::function<void()> and use boost::bind to bind it.
std::function<void()> fun = boost::bind(class::member_fun, args);
EDIT
What about making your B class a template so you can do this:
#include<iostream>
class A {
public:
void aFunction() { // <- this is the function I want to point at
std::cout << "aFunction() is called\n";
}
};
template<class T>
class B {
public:
void setFunction( void (T::*func)() ) {
p_func = func;
}
void (T::*p_func)(); // the function pointer
void callfunc()
{
(t.*p_func)(); //call pointer to member
}
private:
T t;
};
int main() {
B<A> obj;
obj.setFunction(&A::aFunction);
return 0;
}
Live Example
I found the complete answer myself while searching for a way to save *objects of an unknown type without using templates or void pointers which has been answered here. The solution is a bit dodgy, because you'll have to create a dummy parent which allows for certain conversions.
The idea is that you create a Parent and every object that is allowed to be pointed to must inherit from it. This way you can create a pointer as Parent *obj which can hold multiple types of objects, but of course only classes that inherit from Parent.
The same applies for function pointers. If you define your pointer as void (Parent::*func)() as member variable. You can ask the user a template function pointer template <class Class> setFunction( void (Class::*f)() ), which can hold any pointer to any class. Now you need to cast the function pointer to the desired class, Parent: static_cast<void(Parent::*)()>(f). Mind that this only works when Class inherits from Parent. Otherwise you'll get a compilation error.
Minimal Working Example
#include <iostream>
using namespace std;
// dummy class Parent
class Parent {};
// class A
class A : public Parent { // Mind the inheritance!
public:
A(int n) : num(n) {}
void print() { // <- function we want to point to
cout << "Number: " << num << endl;
}
int num;
}
// class B, will hold the 2 pointers
class B {
public:
B() {}
template <class Class> // will save the function and object pointer
void setFunction( void (Class::*func)(), Class *obj) {
function = static_cast<void(Parent::*)()>(func);
object = obj;
}
void execFunction() { // executes the function on the object
(object->*function)();
}
void (Parent::*function)(); // the function pointer
Parent *object; // the object pointer
}
int main() {
A a(5);
B b;
b.setFunction(&A::print, &a);
b.execFunction();
return 0;
}
I don't really like this solution. A better solution would be that class B could have a function where it returns a bool when the function needs to be executed. This way you could simply place an if statement in the main-function that executes the desired function.
A a(5);
B b;
while (;;) {
if (b.aTest())
a.print();
}
Where B::aTest() is declared as
bool B::aTest();
Hope this helps anyone that comes across the same problem. So it is perfectly possible but pretty dodgy in my opinion, and I don't encourage people using the first method.

How to store a function in a member of class? (Using function as callback)

I want to store a function as a class member and call it inside the class? Pretty much like a callback function. My class draw a document but every document must drawn differently. So I want to assign a function (written outside of the class) into one of the members of the class and then call it when I want to draw the document.
This function mostly is responsible for transforming objects according to each specific document.
Here is my class:
class CDocument
{
public:
CDocument();
~CDocument();
void *TransFunc();
}
void Transform()
{
}
int main()
CDocument* Doc = new CDocument();
Doc->TransFunc = Transform();
}
I know that this is probably simple question, but I couldn't find the answer by googling or searching SO.
I think, this is what you might want. Please get back to me if you have questions.
class CDocument
{
public:
CDocument():myTransFunc(NULL){}
~CDocument();
typedef void (*TransFunc)(); // Defines a function pointer type pointing to a void function which doesn't take any parameter.
TransFunc myTransFunc; // Actually defines a member variable of this type.
void drawSomething()
{
if(myTransFunc)
(*myTransFunc)(); // Uses the member variable to call a supplied function.
}
};
void Transform()
{
}
int main()
{
CDocument* Doc = new CDocument();
Doc->myTransFunc = Transform; // Assigns the member function pointer to an actual function.
}
You need to use a Pointer to member function.
typedef void (CDocument::*TransFuncPtr)();
And then you can use TransFuncPtr as an type.
With your edit It seems like you just need a Pointer to a Free function.
Here is a small working sample.
#include<iostream>
#include<string>
typedef void (*TransFuncPtr)();
class Myclass
{
public:
TransFuncPtr m_funcPtr;
};
void doSomething(){std::cout<<"Callback Called";}
int main()
{
Myclass obj;
obj.m_funcPtr = &doSomething;
obj.m_funcPtr();
return 0;
}
The C declaration syntax, inherited by C++, is tricky.
Your declaration
void *TransFunc();
is actually the same as
void* TransFunc();
which declares a function returning a pointer, and not a pointer to a function.
To have the * bind to the declared name, and not to the type, you have to use an extra set of parenthesis
void (*TransFunc)();