How to handle class function pointer - c++

I want to be able to use a member variable to hold the address a function to call
I got the error:
cannot convert 'void (TestClass::*)(bool)' to 'void (*)(bool)' in
assignment
TestClass.cpp
#include "TestClass.h"
TestClass::TestClass()
{
_myFctPtr = &setFired;
}
void TestClass::setFired(bool isFired)
{
_fired = isFired;
}
void TestClass::updateValue()
{
(_myFctPtr)(true);
}
bool TestClass::getFired()
{
return _fired;
}
TestClass.h
#pragma once
class TestClass
{
private:
bool _fired = false;
protected:
void (*_myFctPtr)(bool);
public:
TestClass();
void setFired(bool);
void updateValue();
bool getFired();
};

The error:
cannot convert 'void (TestClass::*)(bool)' to 'void (*)(bool)' in assignment
Is showing you that pointers to class member functions have a different type from regular function pointers. This is because, in addition to the regular function arguments and return type, these functions are differentiated by the object they are called on (i.e. their this), which must be provided when invoking them.
Specifically, for a pointer to a function on TestClass which accepts a bool argument as shown here, you need to to define your field as the type void (TestClass::*)(bool):
void (TestClass::*_myFctPtr)(bool);
You can call this like so, assuming you want to invoke the method on this:
((this).*(_myFctPtr))(true);
This article provides additional useful information and advice on better, cleaner ways to invoke pointers to member functions - e.g. using std::invoke for cleaner syntax than what I provided above - but this is the bare minimum to quickly solve your issue.

Related

Function pointers on a class's member function

void Parser::add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand)
{
command_no_arg.push_back(comand);
func_no_arg.push_back(f);
}
void Parser::prepare()
{
//add_func_no_arg(Virtual_Machine::dump,"dump"); it work when i put it in static but i cant do that
add_func_no_arg(vm.clear,"clear"); // ERROR HERE the vm.clear does not fit
}
I have those two functions to try help my create a array of pointers func_no_arg;
I can't put the vm's func in static;
Why cant i have a pointer on a function when it is "trap" whit in one objet ? maybe the type is wrong, here is some .hpp :
class Parser {
public:
/***/
void prepare();
void add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand);
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
/***/
};
class Virtual_Machine {
public:
/***/
void clear();
/***/
}
and the compiler said this :
Parser.cpp: In member function ‘void Parser::prepare()’:
Parser.cpp:65:36: error: invalid use of non-static member function ‘void Virtual_Machine::clear()’
add_func_no_arg(vm.clear,"dump");
^
In file included from ../include/Parser.hpp:13,
from Parser.cpp:8:
../include/VM.hpp:23:14: note: declared here
void clear();
The syntax for getting a pointer-to-member is &Virtual_Machine::clear (not vm.clear), and a variable f of this type can be invoked on an instance of Virtual_Machine with the .* operator (e.g. vm.*f()).
Alternatively you could write &decltype(vm)::clear, which doesn't depend on the class name.
As written by IlCapitano you have to use a specific syntax to deal with pointer-to-members. Here is an example (compiled with g++ tmp.cpp -o tmp):
#include <iostream>
#include <string>
#include <vector>
class Virtual_Machine
{
private:
std::string name;
public:
Virtual_Machine(std::string n) : name(n) {}
void clear() { std::cout << "Clear " << name << std::endl; }
};
class Parser
{
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
public:
Parser(std::string vm_name) : vm(vm_name) {}
void add_func_no_arg(void (Virtual_Machine::* f)(), std::string command)
{
command_no_arg.push_back(command);
func_no_arg.push_back(f);
}
void prepare()
{
add_func_no_arg(&Virtual_Machine::clear, "clear");
}
void test()
{
(vm.*(func_no_arg[0]))();
}
};
int main()
{
Parser a("vm_a"), b("vm_b");
a.prepare();
b.prepare();
a.test();
b.test();
return 0;
}
The output of the program is:
Clear vm_a
Clear vm_b
A pointer to the member function clear of an instance of class Virtual_Machine is created with &Virtual_Machine::clear. To later call this function you have to use the operators .* or ->* with an instance of the class on the left side of the operator and the pointer to the function on the right side, like (vm.*(func_no_arg[0]))(). If the function would have parameters, you would place them in the most right pair of parentheses.
As mentioned above, the proper syntax to get a pointer to a member functions is &Class::member. The general idea behind this, is that when you declare a class, every function and types in that class belongs in a namespace named after your class. Thus the syntax for getting a pointer to member function is actually equivalent to any pointer to a function inside a namespace. Do keep in mind that access specifier still apply when trying to retrieve a pointer to a function in a class.
However, there is one big difference, in that when you declare a member function, an implicit parameter is added (this in c++), which you actually noted, which is why the type is return_type (Class::*) (parameters)
There are two way to handle this matter. The first one, as noted by others here is to use the instance when you need to call the function, by using the .* or ->* syntax (the dot or arrow are there to access the instance "internals", and the star to de-reference the function pointer).
Another way of doing this (mostly if you don't care about the object, or can't access it when you call it) is to wrap your function in an std::function, by "binding" the implicit this, and any parameter you need to, using std::bind.
By using std::function and std::bind together, you would be able to use the c-style syntax you're used to.
The example section for std::function and std::bind on cppreference show how to achieve this

pass a function pointer between classes

I have two claces.
here is the first one
class one{
one(){ }
public:
void change(double a){
//print a
}
void run(){
two tw;
tw->functionpointer=&change;
}
};
and here is the two class
public two{
two();
static void progresschange(double v){
functionpointer(v);
}
public:
void (*functionpointer)(double);
};
as you see in example I have a function in class one, I want to call it from an static function in class two As progresschange is static I can only call change function in class one uisng function pointers. but It does not work and compiles says
error: cannot convert ‘void (one::*)(double)’ to ‘void (*)(double)’ in assignment
it happens in this line
tw->functionpointer=&change;
how can I make it work. it is even possible to pass a function using its function pointer to another class using this method?
thanks
The error message is quite straightforward:
error: cannot convert void (one::*)(double) to void (*)(double) in assignment
void one::change(double) is a member function of the class one, not just a function. Therefore, you can't assign a pointer to this member function (i.e.: void (one::*)(double)) to a pointer to a function with the same signature (i.e.: to a void (*)(double)).
Besides, a non-static member function (like one::change() above) has to be called on an object, so you also need to provide an one object to call that pointed-to non-static member function.
Basically, you can achieve what you want by adding the following data members in two:
void (one::*mem_func_ptr)(double);
one *obj_ptr;
That is, a pointer to the member function (mem_func_ptr) and a pointer to the object to call this member function on (obj_ptr).
To assign to the member function pointer:
mem_func_ptr = &one::change;
Then, to call the member function pointed by mem_func_ptr on the object pointed by obj_ptr with 0.0 as argument:
(obj_ptr->*mem_func_ptr)(0.0);
It can be done analogously by keeping a copy of an object one as data member instead of a ponter. In that case you should use the operator .* instead of ->*.
The problem is that one::change() is a class member so you need to pass a pointer to a class instance as well.
The modern way to do it is to use std::function, std::bind and std::mem_fn:
class two {
....
std::function<void(double)> functionpointer;
}
tw->functionpointer = std::bind(std::mem_fn(&one::change), _1, one_instance);
Alternatively you can use a lambda function:
tw->functionpointer = [&one_instance](double x) { one_instance->change(x); }

Calling Member Function Pointers

I am having trouble calling a function pointer inside a structure. I have used this approach before outside of classes, but now that I am trying it inside a class method using function pointers to other class methods.... I am receiving a compiler error. Here is my class:
class Myclass
{
int i;
void cmd1(int)
{}
void cmd2(int)
{}
void trans()
{
const struct
{
std::string cmd;
void (Myclass::*func)(int)
}
CmdTable[] =
{
{ "command1", &Myclass::cmd1 },
{ "command2", &Myclass::cmd2 }
};
CmdTable[0].func(i);
CmdTable[1].func(i);
}
};
The lines CmdTable[0].func(i); and CmdTable[1].func(i); both provide the following
error:
Error: expression must have (pointer-to-) function type.
I realize there are probably better ways of doing this, but I'm rather curious as to why what I've written doesn't work. Any explanation would be greatly appreciated.
The pointer-to-member-function is a pure class property. You need to combine it with a class instance in order to make a meaningful function call. For example, to use the instance *this, you can use the operator ->* and say:
(this->*CmdTable[0])(i);
Or you can use operator .* on an object value:
(*this.*CmdTable[0])(i);
The latter form is always correct. For the former, note that operator->* may be overloaded and do something unrelated.

Restricting functions that can be passed to another function in C++

I have a class containing several very similar functions and a couple other functions that take those interchangeably functions as input.
A simpler example:
class functions{
public:
int a();
int b();
int F(int (*f)() ); //f can only be a() or b()
};
Before I put them in a class, I had something like
if(f!=a || f!=b) cout<<"error";
With the class, it seems to just get more complicated, since I believe I now need to pass a class instance or something to get rid of my error: invalid use of member function
I have just started to learn about enumerated lists, and it seems like that would do the job if I was dealing with normal variables. Can I create an enum of functions?
What is the best way to restrict functions that can be passed to another function?
I'm pursuing the static cast method, but still needing help with int F( int(*f)() );
int functions::F(int (functions::*f)() )
{
if(f==functions::a)
//gives error: invalid operands of types 'int (functions::*)()'
// and 'int (int(*)()' to binary operator =='
int x=f();
//gives error: must use ‘.*’ or ‘->*’ to call pointer-to-member
//function in 'f(...)'
int y=(functions.*f)();
//gives error: expected primary-expression before ‘.*’ token
return 0;
}
It really depends on what you want to achieve:
I'd say largely that this sort of restriction is best validated by code review rather than coding...
The other solution is to not use that construct at all, and making a Fa() and Fb() function that calls the (private) a() and b() member functions.
And the remainder of the question is "how do I call a member function of a class" -the answer to which depends highly on whether Functions has member variables that are used in a() and b() or not. If there are no member functions, then declaring the a() and b() members as static will work. On the other hand, if you want to use a "member function pointer", the syntax is int (Functions::*f) and &Functions::a respectively, and the call has to be made using an instance of Functions. so if we have Functions fun, you'd do fun.*f(). Or (*this).*f(), insice F().
You may wrap the accepted function in a class:
#include <iostream>
class Functions
{
public:
int a() { return 0; }
int b() { return 1; }
};
class Accept
{
public:
typedef int (Functions::*AcceptFunction)();
int apply(Functions& object, AcceptFunction function) {
return (object.*function)();
}
};
int main()
{
Functions functions;
Accept accept;
std::cout << accept.apply(functions, &Functions::b) << std::endl;
}
(Feel free to bundle it by making Functions a nested class in Accept)

C++ Passing a pointer to a member function as an argument

I need to pass a pointer to a member function as an argument to a member function in another class. What I'm doing is something like below.
I want to call int Processor::AddJob(void (_pFunc)(void*), void* _pArg) method with void* ProcessHandler::Task(void* a) as the first argument.
I did it as
TaskFunc pFunc1 = &ProcessHandler::Task;
p_Processor->AddJob(pFunc1,10);
But it gives the error
error: no matching function for call to Processor::AddJob(void*
(ProcessHandler::&)(void), int)’ Processor.h:47: note: candidates
are: int Processor::AddJob(void* ()(void), void*)
Can someone please help me on this.My implementation is as follows.(Not the exact code-it is much larger than this)
class Processor
{
public:
Processor();
virtual ~Processor();
int AddJob(void *(*_pFunc)(void*), void* _pArg);
};
int Processor::AddJob(void *(*_pFunc)(void*), void* _pArg)
{
//Job addition related code goes here
}
/////////////////////////////////////////////////////////////////////////////
typedef void* (ProcessHandler::*TaskFunc)(void*);
class ProcessHandler
{
public:
ProcessHandler(Processor* _pProcessor);
virtual ~ProcessHandler();
void* Task(void* a);
void Init();
private:
Processor* p_Processor;
};
void* ProcessHandler::Task(void* a)
{
//Task related code goes here
}
void ProcessHandler::Init()
{
TaskFunc pFunc1 = &ProcessHandler::Task;
p_Processor->AddJob(pFunc1,10); //This give the compile error.
}
/////////////////////////////////////////////////////////////////////////
int main()
{
Processor* pProcessor = new Processor();
ProcessHandler* pProcessHandler = new ProcessHandler(pProcessor);
pProcessHandler->Init();
}
You can only pass static member functions via the address-of operator. Regular member functions don't work. You should consider using std::function.
In C++ I would suggest to do_NOT use pointers to functions(raw pointers are arguable too).
You should use std::function(boost::function) for more generality, or
template. Latter gives you a bit perfomance, but less typecheck.
void (_pFunc)(void*) is a C-Function pointer, and as such, you can only either pass C-Functions via that pointer, or static functions.
void (ProcessHandler::*)(void); //Since you already have a Typedef, pass that as 'type'
should help you call a member function.
Call it with the pointer to member function calling syntax:
(objectPointer->*functionPointer)();