I'm using C++ (not C++11). I need to make a pointer to a function inside a class. I try to do following:
void MyClass::buttonClickedEvent( int buttonId ) {
// I need to have an access to all members of MyClass's class
}
void MyClass::setEvent() {
void ( *func ) ( int );
func = buttonClickedEvent; // <-- Reference to non static member function must be called
}
setEvent();
But there's an error: "Reference to non static member function must be called". What should I do to make a pointer to a member of MyClass?
The problem is that buttonClickedEvent is a member function and you need a pointer to member in order to invoke it.
Try this:
void (MyClass::*func)(int);
func = &MyClass::buttonClickedEvent;
And then when you invoke it, you need an object of type MyClass to do so, for example this:
(this->*func)(<argument>);
http://www.codeguru.com/cpp/cpp/article.php/c17401/C-Tutorial-PointertoMember-Function.htm
You may want to have a look at https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types, especially [33.1] Is the type of "pointer-to-member-function" different from "pointer-to-function"?
you only need to add parentheses after the function call and pass arguments if needed
Related
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); }
In my code I would like to call different functions by the same name. So I used pointers, and I did work with static functions, now I would like to do the same with non-static functions and it doesn't work at all.
class Amrorder
: {
public:
....
void (*fkt)(real&, const real);
void fktAcPulse(real &rhoRef, const real y);
void fktAcPulseSol(real &rhoRef, const real y);
...
}
void Amrorder::initData(a)
{
...
switch(method){
case 2://
Amrorder::fkt=&Amrorder::fktAcPulse;
break;
case 222://
Amrorder::fkt=&Amrorder::fktAcPulse1d;
break;
}
...
for(int i=0; i<ng; ++i){
Amrorder::fkt(rhoRef, yRef);
...
}
...
}
The code is quiet big so I hope the part above is enough to understand what I want to do.
Thanks for your time!
It doesn't work because your fkt has type:
void (*)(real&, const real);
and you're trying to assign it to, e.g., &Amrorder::fktAcPulse, which has type:
void (Amrorder::*)(real&, const real);
Notice the difference. The latter is a pointer-to-member function, not just a pointer to function. These have different semantics. A pointer to function can just be called (e.g. fkt(a, b)), but a pointer to member function needs to be called on an object (e.g. (obj.*pm)(a, b)).
For simplicity, since you probably just want "something that I can call with a real& and a const real", you may want to consider the type-erased function object: std::function:
std::function<void(real&, const real)> fkt;
This can be initialized with any callable that matches the arguments, so you can assign it to a free function:
void foo(real&, const real) { ... }
fkt = foo;
A static member function:
struct S { static void bar(real&, const real) { ... } };
fkt = &S::bar;
Or a member function, as long as its bound:
fkt = std::bind(&Amrorder::fktAcPulse, this);
fkt = [this](real& a, const real b){ return this->fktAcPulse(a, b); };
The key is that you need an instance of Amrorder to call fktAcPulse, and using std::function lets you use either std::bind or a lambda to store that instance in with the functor itself.
The type of fkt declares a function pointer to a free-standing function or a static member function. But you want to assign a non-static member function pointer to it. So fkt needs to be of the type of a non-static member function pointer of class Amrorder. That type is spelled
void (Amrorder::*fkt)(real&, const real);
// ^^^^^^^^^^
When invoking a function pointer to a non-static member function, you need to specify on which object you want the member to be called (which normally defaults to this when calling a member function directly with its name).
The syntax for this is quite strange. It requires another pair of parentheses and depends on wether you call it on a pointer or an object itself:
(object.*functionPointer)(arguments);
(pointer->*functionPointer)(arguments);
So if you just want to call the function on the this pointer, you need to write
(this->*fkt)(rhoRef, yRef);
(Note that you don't need to specify the class in your code everywhere. Amrorder:: can be removed in front of every function name inside the definition of a member function of the same class.)
When you call a non-static method of a class, the compiler needs to know which instance of the class you want to execute against. So there is a hidden parameter in the call, which is a pointer to the instance.
So you need to write something like this:
Amrorder::fkt=bind( &Amrorder::fktAcPulse, this );
I'm using C++ (not C++11). I need to make a pointer to a function inside a class. I try to do following:
void MyClass::buttonClickedEvent( int buttonId ) {
// I need to have an access to all members of MyClass's class
}
void MyClass::setEvent() {
void ( *func ) ( int );
func = buttonClickedEvent; // <-- Reference to non static member function must be called
}
setEvent();
But there's an error: "Reference to non static member function must be called". What should I do to make a pointer to a member of MyClass?
The problem is that buttonClickedEvent is a member function and you need a pointer to member in order to invoke it.
Try this:
void (MyClass::*func)(int);
func = &MyClass::buttonClickedEvent;
And then when you invoke it, you need an object of type MyClass to do so, for example this:
(this->*func)(<argument>);
http://www.codeguru.com/cpp/cpp/article.php/c17401/C-Tutorial-PointertoMember-Function.htm
You may want to have a look at https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types, especially [33.1] Is the type of "pointer-to-member-function" different from "pointer-to-function"?
you only need to add parentheses after the function call and pass arguments if needed
I'm trying to implement Marmalade's IwBilling (c++) but all is what I get is the error: "Reference to non-static member function must be called".
I use the following code:
=== [ main cpp file ] ===
#include <s3e.h>
#include "MyGame.h"
int main () {
IwGxInit();
{
MyGame game = new MyGame();
}
IwGxTerminate();
}
=== [ MyGame.h ] ===
#include "IwBilling.h"
class MyGame{
void billingError( void* caller, IwBilling::CIwBillingErrorData* data ) {}
MyGame() {
if ( IwBilling::isAvailable() && IwBilling::Init() ) {
IwBilling::setErrorCallback( billingError ); // !!! ERROR: Reference to non-static member function must be called
}
}
};
What's the problem here? Why do this works like this? If I write: "static void billingError" all works fine. But I don't know if that correct to use static before void billingError?
I don't understand why my MyGame() constructor is a static method? How can I do it non-static?
In C++, nonstatic member functions are always associated with an instance of the class that they are declared within. Thus in order to call them, you have to have an instance of that class available. So if billingError() is declared nonstatic, you would have to call it with an instance of MyGame like this:
MyGame* myGame = new MyGame();
myGame->billingError(); // myGame is the instance for this call
Static functions can be called without an instance of the class like so:
MyGame::billingError(); // assuming billingError() was declared static
The reason for this distinction is nonstatic member functions have an implicit 'this' pointer passed to them, which is a pointer to the instance that the function is called on (myGame in the first example would be the 'this' pointer inside of that function). The 'this' pointer is passed as an invisible parameter to the function. Static functions on the other hand don't have any extra implicit parameters.
Because the two types of functions have different calling conventions, pointers to them are treated differently. So if you wanted to use a nonstatic billingError() function, you would have to declare setErrorCallback() to take a nonstatic function pointer and pass an instance of MyGame. For example:
class IwBilling {
void setErrorCallback( void (MyGame::*callback) (void* caller, IwBilling::CIwBillingErrorData* data), MyGame* instance ) {
// do some stuff
instance->callback(caller, data);
}
}
On the other hand, if you don't need an instance of myGame, then you can declare billingError() static, and declare the setErrorCallback() callback parameter as a static function pointer like this:
class IwBilling {
void setErrorCallback( void (*callback) (void* caller, IwBilling::CIwBillingErrorData* data) ) {
// do some stuff
callback(caller, data);
}
}
Unfortunately, IwBilling callbacks do not follow the usual pattern of passing along a user-defined void* which you could use to indicate which instance of your class to invoke the method upon. So you are probably stuck with some static ugliness like this:
class MyGame{
static MyGame* instance; // define and initialize this in your .cpp file
void billingError( void* caller, IwBilling::CIwBillingErrorData* data ) {}
static void billingErrorStatic( void* caller, IwBilling::CIwBillingErrorData* data ) {
instance->billingError(caller, data); // call the non-static method
}
MyGame() {
if ( IwBilling::isAvailable() && IwBilling::Init() ) {
IwBilling::setErrorCallback( &MyGame::billingErrorStatic );
}
}
};
I got the following error from the code below.
error: invalid use of member 'calls_object::OBJECT' in static member function|
error: from this location
from the line OBJECT->call(); line 29.
Basically the function must be static because its really a simplified version of the code
which creates a windows thread. I just can't seem to use pointers within a static function but I can create the object within the static function no problem. Is there another way?
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)windowsthread, (LPVOID)i, NULL, &m_id);
static DWORD_PTR WINAPI windowsthread()
{
OBJECT->call();
}
l
class object
{
private:
public:
object(){}
~object(){}
void call(){}
};
class calls_object
{
private:
object* OBJECT;
public:
calls_object()
{
OBJECT = new object();
}
~calls_object(){}
#ifdef _WIN32
static void windows_function()
{
OBJECT->call();
}
#endif
};
int main()
{
calls_object O;
}
This function:
static void windows_function()
{
OBJECT->call();
}
Is declared as static. It means it does not receive an implicit this pointers: in other words, it does not operate on an instance of calls_object. Therefore, it cannot see the OBJECT member variable.
Either declare the function as non-static, or declare OBJECT as a static member variable (whatever makes more sense in your application).
Basically the function must be static because its really a simplified version of the code which creates a windows thread
Since you are (unfortunately) dealing with a function (CreateThread) that accepts a function pointer, you cannot even use std::bind. However, CreateThread lets you provide a function which accepts a pointer (to void, see the prototype of ThreadProc).
Just pass a pointer to an object as the fourth argument to CreateThread, and let windowsFunction(void*) receive that pointer. Inside windowsFunction(), which would still be static or global (in fact, you do not need the calls_object class at all), you can cast that pointer to a pointer to object and invoke call() on it.
Also notice, that your class calls_object is leaking memory, since you are forgetting to delete the pointer you created in calls_object's constructor:
~calls_object()
{
delete object; // DON'T FORGET THIS!
}
windows_function is a static member function, so is not associated with any calls_object object. OBJECT is a non-static data member, so is associated with a calls_object object. You cannot access a non-static data member from a data member.
Simply make the function non-static and it will work.
Think of it this way. If you didn't even create an object of type calls_object and your main function was just:
int main()
{
calls_object::windows_function();
}
Where would you expect this function to get OBJECT from? Since OBJECT is a non-static member, it only exists as part of a calls_object object. A static member function cannot simply pull OBJECT from nowhere.