I'm trying to pass a function as argument to another function with void pointer and it doesn't work
#include <iostream>
using namespace std;
void print()
{
cout << "hello!" << endl;
}
void execute(void* f()) //receives the address of print
{
void (*john)(); // declares pointer to function
john = (void*) f; // assigns address of print to pointer, specifying print returns nothing
john(); // execute pointer
}
int main()
{
execute(&print); // function that sends the address of print
return 0;
}
The thing are the void function pointers, I could make an easier code like
#include <iostream>
using namespace std;
void print();
void execute(void());
int main()
{
execute(print); // sends address of print
return 0;
}
void print()
{
cout << "Hello!" << endl;
}
void execute(void f()) // receive address of print
{
f();
}
but I wonna know if I can use void pointers
it is for implement something like this
void print()
{
cout << "hello!" << endl;
}
void increase(int& a)
{
a++;
}
void execute(void *f) //receives the address of print
{
void (*john)(); // declares pointer to function
john = f; // assigns address of print to pointer
john(); // execute pointer
}
int main()
{
int a = 15;
execute(increase(a));
execute(&print); // function that sends the address of print
cout << a << endl;
return 0;
}
Using gcc test.cpp I get:
test.cpp: In function ‘void execute(void* (*)())’:
test.cpp:12:22: error: invalid conversion from ‘void*’ to ‘void (*)()’ [-fpermissive]
test.cpp: In function ‘int main()’:
test.cpp:18:19: error: invalid conversion from ‘void (*)()’ to ‘void* (*)()’ [-fpermissive]
test.cpp:9:6: error: initializing argument 1 of ‘void execute(void* (*)())’ [-fpermissive]
The signature for the f argument is incorrect. You need to use
void execute(void (* f)())
instead. Therefore, you don't need the cast when assigning to john:
john = f
Also, you can simplify this by calling f directly:
f(); // execute function pointer
EDIT: Since you want to use void pointers, you need to pass f as a void pointer:
void execute(void *f)
Here, you will need the assignment to john, but as f is already a void * you don't need the cast.
NOTE: Given that you are passing a void pointer, the execute function will accept anything and you will have runtime errors if you pass the wrong thing. For example:
void print_name(const char *name)
{
printf("%s", name);
}
void execute1(void *f);
void execute2(void (*f)());
int main()
{
int value = 2;
execute1(&value); // runtime crash
execute1(&print_name); // runtime crash
execute2(&value); // compile-time error
execute2(&print_name); // compile-time error
}
Using a specifically defined function pointer lets the compiler generate an error at the point where you have passed the wrong argument type. This is preferred to crashing at runtime, as the runtime crash may be exploited as a security vulnerability and requires extensive testing to ensure this error does not occur.
Use
void execute(void (*f)()) //receives the address of print
Or better use:
void execute(boost::function<void()> const & f) //receives the address of print
To accept functors as well, or replace boost:: with std:: if you are using compiler which supports C++11
Related
This question already has answers here:
Explanation of function pointers
(4 answers)
Closed 2 years ago.
How to pass a function pointer as argument with an argument?
void A(){
std::cout << "hello" << endl;
}
void B(void (*ptr)()){ // function pointer as agrument
ptr(); // call back function "ptr" points.
}
void C(string name){
std::cout << "hello" << name << endl;
}
void D(void (*ptr2)(string name)){ // function pointer as agrument
ptr2(name); // error 1
}
int main(){
void (*p)() = A; // all good
B(p); // is callback // all good
void (*q)(string name) = C;
D(q)("John Doe"); // error 2
return 0;
};
errors:
1 - use of undeclared identifier 'name'
2 - called object type 'void' is not a function or function pointer
You should make D taking two parameters, one for the function pointer, one for the argument to be passed to function pointer. E.g.
void D(void (*ptr2)(string), const string& name){
ptr2(name);
}
then call it like
D(q, "John Doe");
name is a part of type declaration for ptr2 and is not a variable in D.
Tou are trying to call what is returned from D, which is void. , is used to separate arguments in C++.
Try this:
#include <iostream>
#include <string>
using std::endl;
using std::string;
void A(){
std::cout << "hello" << endl;
}
void B(void (*ptr)()){ // function pointer as agrument
ptr(); // call back function "ptr" points.
}
void C(string name){
std::cout << "hello" << name << endl;
}
void D(void (*ptr2)(string name), string name){ // function pointer and a string as agrument
ptr2(name);
}
int main(){
void (*p)() = A; // all good
B(p); // is callback // all good
void (*q)(string name) = C;
D(q, "John Doe"); // pass 2 arguments
return 0;
} // you don't need ; here
I am having difficulty calling a pointer to a member function on an object that was cast from void*. See below example:
class Test
{
public:
Test(int pointTo)
{
if (pointTo == 1)
function = &Test::Function1;
else
function = &Test::Function2;
}
static void CallIt(void* cStyle)
{
Test* t(static_cast<Test*>(cStyle));
(t->*function)();// error C2568: '->*': unable to resolve function overload
}
void CallIt()
{
(this->*function)();// Works just fine
}
private:
typedef void (Test::*ptrToMemberFunc)();
ptrToMemberFunc function;
void Function1()
{
std::cout << "Function 1" << std::endl;
}
void Function2()
{
std::cout << "Function 2" << std::endl;
}
};
int main()
{
Test t1(1);
Test t2(2);
Test::CallIt(static_cast<void*>(&t1));
Test::CallIt(static_cast<void*>(&t2));
t1.CallIt();
t2.CallIt();
return 0;
}
What happens when the object is cast to void* and back? Why can I no longer call the pointer to member function?
EDIT:
Modifying CallIt() as follows allows the program to compile, but I'm still curious as to why the original didn't work.
static void CallIt(void* cStyle)
{
Test* t(static_cast<Test*>(cStyle));
Test::ptrToMemberFunc pf(t->function);
(t->*pf)();
}
main.cpp:17:14: error: invalid use of member 'function' in static member function
(t->*function)();// error C2568: '->*': unable to resolve function overload
^~~~~~~~
function is a non-static data member, so you cannot access it from a static function.
If you want to refer to t's function, you can do it like so:
(t->*(t->function))();
Here's a simple (and a silly one, yeah) example of what I'm trying to do:
#include <iostream>
void callFunctionsFromAnArray(void *(*)(int), int);
void f1(int);
void f2(int);
void f3(int);
int main()
{
const int n = 3;
void (*functions[n]) (int) = { f1, f2, f3 };
callFunctionsFromAnArray(functions, n);
}
void callFunctionsFromAnArray(void *(*f) (int), int fCount) {
for (int i = 0; i < fCount; i++)
f[i](1);
}
void f1(int a)
{
std::cout << a * 1 << '\n';
}
void f2(int a)
{
std::cout << a * 2 << '\n';
}
void f3(int a)
{
std::cout << a * 3 << '\n';
}
And those are the errors I'm getting when trying to compile:
12:9: error: no matching function for call to 'callFunctionsFromAnArray'
callFunctionsFromAnArray(functions, n);
3:10: note: candidate function not viable: no known conversion from 'void (*[3])(int)' to 'void *(*)(int)' for 1st argument
void callFunctionsFromAnArray(void *(*)(int), int);
17:13: error: subscript of pointer to function type 'void *(int)'
f[i](1);
2 errors generated.
However, if I change argument to be void (*f[3]) (int) it works. But the problem is, it's not always possible to know array's size before run-time (that's why function has 2nd argument after all). Is there any solution?
Since in this case, the array decays into a pointer, you don't have to know its size beforehand -- inside a function argument declaration, and only there, the pointer and the array qualifier (* and []) are equivalent, and the size of the array doesn't matter.
As a result, you can declare your function to take an array of 3 (or however many) pointers, and then you can pass it an array of any pointers:
void callFunctionsFromAnArray(void *(*f[1])(int), int fCount)
{
for (int i = 0; i < fCount; i++)
f[i](i);
}
However, if you don't like this, you can just make it accept a pointer-to-pointer:
void callFunctionsFromAnArray(void *(**f)(int), int fCount); // etc.
However, if this really is C++, you'd be better off passing a const reference to a vector of std::functions:
void callFunctionsFromAnArray(const std::vector<std::function<void *(int)> > &a)
{
// call'em
}
Since you are using C++ and not C, I highly suggest you to use std::vector and std::function instead. They will make your life much easier, especially in this particular case:
#include <functional>
#include <vector>
void f1(int);
void f2(int);
void f3(int);
using function_vector = std::vector<std::function<void(int)>>;
void callFunctions(const function_vector& vec) {
for (const auto& f : vec)
f(1);
}
int main() {
function_vector vec = { &f1, &f2, &f3 };
callFunctions(vec);
}
You can see a live example here.
Hi I got a question about permissions on c++ member function.
Example 1
class Test {
private:
void func() { cout << "test" << endl; }
};
void weird_func(Test* t, void (Test::*f)()) {
(t->*f)();
}
int main() {
Test t;
weird_func(&t, &Test::func);
}
This wouldn't work
test1.cc: In function ‘int main()’:
test1.cc:10:10: error: ‘void Test::func()’ is private
test1.cc:19:26: error: within this context
However, another example works
class Test {
public:
void helper(Test* ptr);
private:
void func() { cout << "test" << endl; }
};
void weird_func(Test* t, void (Test::*f)()) {
(t->*f)();
}
void Test::helper(Test* ptr) {
weird_func(ptr, &Test::func);
}
int main() {
Test t;
t.helper(&t);
}
I don't quite understand why would the second example work. The only difference is that it has a helper function. Test::func is invoked in weird_func for both examples, which is not a member of class Test. I guess there is some information about permission stored with the member function pointer. Would someone confirm (or deny) this and explain a bit of the reason under the hood?
Thanks,
Di
::helper has access to the private function and thus can address it, or in this case pass the address to another function. Once it's referenced as a function pointer it can be passed around just as you could with a pointer to a class attribute. It's dangerous in the wrong hands :).
This question is related to my another question- boost::bind return a function object which is the argument for a function that requires pointer
Except the interface of
bridge_set_pound_var_func
is not allowed to be changed.
Also, boost::function or boost::bind do not work well with the large project.
My new code is as follows:
#include <iostream>
class myA
{
public:
int bridge_set_pound_var_func(int (*fp)(const char *, char *, void *), void *arg)
{
void * b = NULL;
int a = fp("this is poundVar", "ths is t1", b) ;
std::cout << "bridge_set_pound_var_func is called "<< " , a is " << a << std::endl ;
return 0;
}
};
class myC
{
public:
myA *myOA;
int func(const char * poundVar , char * t1, void * t2);
int myCCall()
{
myA myAO;
myOA = &myAO;
std::cout << "myCCall is called " << std::endl;
myOA->bridge_set_pound_var_func( &myC::func, (void *)this );
return 0;
}
};
int myC::func(const char * poundVar , char * t1, void * t2)
{
std::cout << "myC::func is called " << std::endl;
return 1;
}
int main()
{
myC myCO ;
myC *m1p = &myCO ;
m1p->myCCall() ;
return 0 ;
}
// EOF
The errors on Linux :
In member function 'int myC::myCCall()':
error: no matching function for call to 'myA::bridge_set_pound_var_func(int (myC::*)(const char*, char*, void*), void*)'
candidates are: int myA::bridge_set_pound_var_func(int (*)(const char*, char*, void*), void*)
errors on VMS:
In member function 'int myC::myCCall()':
error: no matching function for call to 'myA::bridge_set_pound_var_func(int (myC::*)(const char*, char*, void*), void*)'
candidates are: int myA::bridge_set_pound_var_func(int (*)(const char*, char*, void*), void*)
The short answer is: pointers to member functions are not pointer to functions. The former need to know about the object they are called on, the latter don't. A typical approach used is to use the usually present "user data" void* to point to a suitable base class, cast the pointer and call a corresponding virtual function. Frim there you can recover the necessary object context easily.