Please explain me why the code below doesn't work
#include <stdio.h>
int foo() { return 1; }
int bar() { return 2; }
void ass()
{
foo=bar;
}
int main()
{
ass()
}
The following error
test.cpp: In function ‘void ass()’:
test.cpp:8:8: error: assignment of function ‘int foo()’
test.cpp:8:8: error: cannot convert ‘int()’ to ‘int()’ in assignment
caused.
You must use a function pointer. You cannot assign to the function itself.
int(*baz)() = &foo;
baz();
try this:
typedef int (*int_funcptr_void)(void);
then, you can simply:
int foo() { return 1; }
int bar() { return 2; }
int_funcptr_void func;
void ass()
{
func = (int_funcptr_void)foo;
}
int main()
{
ass(); //you also forgot a semicolon here, but nice naming
//then, we can call it:
printf("%d\n", func());
}
and get this:
hydrogen:tmp phyrrus9$ ./a.out
1
Hope that helps.
You can not assign function to function, as you can not assign int to int. Think naturally, you assign an int variable to another int variable, which means you are assigning rvalue of the second variable to the lvalue(address) of the first one. Same rule for function, you can assign a function object to another function object. The difference is, function is code, not data, but it has an address ( the starting point). So assigning function to one another generally means assigning the address of the function to a variable which can hold an address, i.e. a function pointer.
void f(){}
typedef void(*pF)(); //typedef for easy use
pf foo; //create a function pointer object
foo = &f; //assign it the address of the function
Related
Hi it is my first experience with passing function pointer in C++.
So here is my code:-
#include <iostream>
using namespace std;
// Two simple functions
class student
{
public:
void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }
// A function that receives a simple function
// as parameter and calls the function
void wrapper(void (*fun)())
{
fun();
}
};
int main()
{ student s;
s.wrapper(s.fun1());
s.wrapper(s.fun2());
return 0;
}
Initially in wrapper function i passed only fun1 and fun2.I got an error
try.cpp:22:15: error: ‘fun1’ was not declared in this scope
s.wrapper(fun1);
^~~~
try.cpp:23:15: error: ‘fun2’ was not declared in this scope
s.wrapper(fun2);
Later I tried to pass s.fun1() and s.fun2() as argument but again got error
try.cpp:23:23: error: invalid use of void expression
s.wrapper(s.fun1());
^
try.cpp:24:23: error: invalid use of void expression
s.wrapper(s.fun2());
Please help I don't know what to do :(
Let's deal with the two issues in the post.
You are calling fun1 and fun2. Since their return type is void, you can't pass their result as something's value. In particular as the value of a function pointer. You also can't obtain their address by using the dot member access operator. Which brings us to the following.
Member functions are not like regular functions. You cannot just take their address. Their treatment is special, because member functions can only be called on an object. So there's a special syntax for them, which involves the class they belong to.
Here's how you would do something like what you are after:
class student
{
public:
void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }
// A function that receives a member function
// as parameter and calls the function
void wrapper(void (student::*fun)())
{
(this->*fun)();
}
};
int main()
{ student s;
s.wrapper(&student::fun1);
s.wrapper(&student::fun2);
return 0;
}
How to invoke an object method passed to a variable?
class A {
public:
inline int f() {
return 1;
}
};
int main() {
A a;
int (A::*y)(); //'y' must be a method of 'A' class that returns 'int'
y = &A::f; //bind 'f' method
*y(); //how to invoke???
}
The other thread bound a method to an object field and it was invoked this way (a.*(a.x))(), but i can't find a way to do a similar thing to a simple variable.
Simply do (a.*y)();. You need the extra parantheses make the compiler resolve the pointer to member before making the function call. See operator precedence:
class A {
public:
inline int f() {
return 1;
}
};
int main() {
A a;
int (A::*y)(); //'y' must be a method of 'A' class that returns 'int'
y = &A::f; //bind 'f' method
(a.*y)();
}
Demo
Alright, I think the title is sufficiently descriptive (yet confusing, sorry).
I'm reading this library: Timer1.
In the header file there is a public member pointer to a function as follows:
class TimerOne
{
public:
void (*isrCallback)(); // C-style ptr to `void(void)` function
};
There exists an instantiated object of the TimerOne class, called "Timer1".
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct? I am familiar with calling functions via function pointers by using the dereference operator.
Ex:
(*myFunc)();
So I would have expected the above call via the object to be something more like:
(*Timer1.isrCallback)();
So, what are the acceptable options for calling functions via function pointers, as both stand-alone function pointers and members of an object?
See also:
[very useful!] Typedef function pointer?
Summary of the answer:
These are all valid and fine ways to call a function pointer:
myFuncPtr();
(*myFuncPtr)();
(**myFuncPtr)();
(***myFuncPtr)();
// etc.
(**********************************f)(); // also valid
Things you can do with a function pointer.
1: The first is calling the function via explicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
(*myfptr)(nValue); // call function myfunc(nValue) through myfptr.
2: The second way is via implicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
myfptr(nValue); // call function myfunc(nValue) through myfptr.
As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since function are simply implicitly convertible to function pointers!!
In your code:
void foo()
{
cout << "hi" << endl;
}
class TimerOne
{
public:
void(*isrCallback)();
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &foo; //Assigning the address
//Timer1.isrCallback = foo; //We could use this statement as well, it simply proves function are simply implicitly convertible to function pointers. Just like arrays decay to pointer.
Timer1.isrCallback(); //Implicit dereference
(*Timer1.isrCallback)(); //Explicit dereference
return 0;
}
You don't have to dereference a function pointer to call it. According to the standard ([expr.call]/1),
The postfix expression shall have
function type or pointer to function type.
So (*myFunc)() is valid, and so is myFunc(). In fact, (**myFunc)() is valid too, and you can dereference as many times as you want (can you figure out why?)
You asked:
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct?
The type of Timer1.isrCallback is void (*)(). It is a pointer to a function. That's why you can use that syntax.
It is similar to using:
void foo()
{
}
void test_foo()
{
void (*fptr)() = foo;
fptr();
}
You can also use:
void test_foo()
{
void (*fptr)() = foo;
(*fptr)();
}
but the first form is equally valid.
Update, in response to comment by OP
Given the posted definition of the class you would use:
(*Timer1.isrCallback)();
To use
(Timer1.*isrCallback)();
isrCallback has to be defined as a non-member variable of whose type is a pointer to a member variable of TimerOne.
void (TimerOne::*isrCallback)();
Example:
#include <iostream>
class TimerOne
{
public:
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
void (TimerOne::*isrCallback)() = &TimerOne::foo;
(Timer1.*isrCallback)();
}
Output:
In TimerOne::foo();
(Test this code)
If you want to define isrCallbak as a member variable of TimerOne, you'll need to use:
#include <iostream>
class TimerOne
{
public:
void (TimerOne::*isrCallback)();
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &TimerOne::foo;
// A little complicated syntax.
(Timer1.*(Timer1.isrCallback))();
}
Output:
In TimerOne::foo();
(Test this code)
I've applied solutions based on some search made, but the problem still there. Thank you so much for the help.
error: must use '.*' or '->*' to call pointer-to-member function ...
source code:
#include <stdio.h>
class A
{
public:
struct data;
typedef int (A::*func_t)(data *);
typedef struct data
{
int i;
func_t func;
}
data;
data d;
void process()
{
d.func(&d);
}
A()
{
d.i = 999;
d.func = &A::print;
}
int print(data *d)
{
printf("%d\n", d->i);
return 0;
}
};
int main()
{
A *a = new A;
a->process();
return 0;
}
d.func(&d);
is not enough. func is a member-function-pointer which is pointing to a non-static member of A. So it can be invoked on an object of A. So you need to write this:
(this->*(d.func))(&d);
That would work as long as you write this inside A.
If you want to execute func from outside, say in main(), then the syntax is this:
A a;
(a.*(a.d.func))(&a.d);
That is an ugly syntax.
Your process function attempts to call d.func but it is a pointer to member function. A pointer to member function must be called on some object. Presumably you want the instance of A to be this, in which case your process function should look like:
void process()
{
(this->*(d.func))(&d);
}
Note the use of the ->* operator to call a member function when you have a pointer to it.
Other answers have already said you need to say (this->*d.func)(&d) to call a pointer-to-member function (because you need to provide the object that it's a member of)
Another option is to make the function a static function, which doesn't need special syntax to call. To do that, change the typedef like so:
typedef int (*func_t)(data *);
Then make the print function static:
static int print(data *d)
{
...
}
Now you can just call d.func(&d)
Unfortunately what you are trying to do will not be possible, the reason being that print is not a static member function. This means it expects an implicit first argument that is the this pointer.
I suggest you try using the std::function and std::bind function, something like this:
class A
{
struct data
{
std::function<void(const data&)> func;
int i;
};
data d;
public:
A()
{
d.func = std::bind(&A::print, *this);
d.i = 999;
}
void process()
{
d.func(d);
}
void print(const data& my_data)
{
std::cout << my_data.i << '\n';
}
};
Of course, since the print function now have a proper this pointer, you no longer need to pass the data structure to it:
class A
{
struct data
{
std::function<void()> func;
int i;
};
data d;
public:
A()
{
d.func = std::bind(&A::print, *this);
d.i = 999;
}
void process()
{
d.func();
}
void print()
{
std::cout << d.i << '\n';
}
};
Calling pointer the members require the class it is a member of to be the this param.
Try:
A a;
a.*(d.func)(&d);
There are several duplicates of this but nobody explains why I can use a member variable to store the pointer (in FOO) but when I try it with a local variable (in the commented portion of BAR), it's illegal. Could anybody explain this?
#include <iostream>
using namespace std;
class FOO
{
public:
int (FOO::*fptr)(int a, int b);
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
fptr = &FOO::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
};
class BAR
{
public:
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
//int (BAR::*fptr)(int a, int b);
//fptr = &BAR::add_stuff;
//cout<<(*fptr)(a,b)<<endl;
}
};
int main()
{
FOO test;
test.call_adder(10,20);
return 0;
}
Apparently, you misunderstand the meaning of this->* in the call in FOO.
When you use this->* with the member fptr pointer, the this->* part has absolutely nothing to do with fptr being a member of FOO. When you call a member function using a pointer-to-member, you have to use the ->* operator (or .* operator) and you always have to specify the actual object you want to use with that pointer-to-member. This is what the this->* portion of the calling expression does. I.e. the call will always look as
(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)
or as
(<object> .* <pointer-to-member>) (<arguments>)
The left-hand side of the call (<pointer-to-object> or <object> above) cannot be omitted.
In other words, it doesn't matter whether fptr is a member variable, local variable, global variable or any other kind of variable, the call through fptr will always look as
(this->*fptr)(a, b);
assuming that you want to invoke it with *this object. If, for another example, you want to invoke it for some other object pointed by pointer pfoo, the call will look as follows
FOO *pfoo;
...
(pfoo->*fptr)(a, b);
In your BAR class the call should look as (this->*fptr)(a,b) even though fptr is a local variable.
When you use a member function pointer, you need to specify the object on which it is acting.
I.e. you need to create a pointer to an instance of BAR (let's call it bar) and do:
(bar->*fptr)(a,b)
to call the function, or an instance of BAR and do:
(bar.*fptr)(a,b)
Put another way:
#include <iostream>
class BAR
{
int i;
public:
BAR(): i(0) {};
int AddOne() { return ++i; };
int GetI() { return i; };
}
int main()
{
BAR bar;
auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
std::cout << (bar.*fPtr)(); //This will print 1 to the console
std::cout << std::endl;
std::cout << bar.GetI(); //This will also print 1 to the console.
}
I don't think the usage of the variable itself is illegal. What's illegal is trying to call that method without a class instance.
That is, you should really call (someVar->*fptr)(a,b) where someVar is of type BAR*
BAR::call_adder() had a couple of problems. For one, you were mixing case. In C++, case is signifigant. BAR and bar are not the same. Second, you decalred and assigned the pointer fine, after fixing the case problems, but when you try to call through the pointer to a member function, you need to use operator ->* with a class object. Here's is call_adder() fixed
void call_adder(int a, int b)
{
int (BAR::*fptr)(int a, int b);
fptr = &BAR::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
When you invoke a member function of a class the compiler generates code to set 'this' while the function runs. When you call it from a function pointer that isn't done. There are ways to get around it but they aren't 'guaranteed' to work and are compiler dependent. You can do it as long as you're careful and know the possible problems you can run into.