This question already has answers here:
C++ function pointer and member function pointer
(3 answers)
Closed 2 years ago.
typedef void (*funcPtrType)(); // function pointer type
map<char,funcPtrType>eventGroups;
void addSharedEvent(char groupIndex,void (*receiverFunc)() ){
if(groupIndex==0)
return;
eventGroups[groupIndex]=receiverFunc;
}
It works if adding inline functions but not if using non inlined class member functions like below...
void MainWin::uiValsUpdated()
{
}
void MainWin::test()
{
//invalid
wSync.addSharedEvent(4,&uiValsUpdated);
}
How to make universal pointer for accessing functions in various types of classes?
Alternatively could define class types also but still in universal manner like Qtˇs signals and slots for example.
typedef void (*funcPtrType)(); // function pointer type
Avoid obfuscating pointer types like this.
It works if adding inline functions but not if using non inlined class member
It has nothing to do inline vs non-inline, and everything to do with the fact that a function pointer cannot point to a non-static member function.
How to make universal pointer for accessing functions in various types of classes?
A function pointer can point to functions except non-static member functions as long as the prototype matches. To call such function, no class instance is required. Example:
void free_function() {}
auto fun_ptr = &free_function;
fun_ptr();
A pointer to member function can point to non-static member functions of a particular class with matching prototype. In order to call such pointed function, there must be an instance of the class. Example:
struct foo {
void member_function(){}
};
auto mem_fun_ptr = &foo::member_function;
foo f;
f.*mem_fun_ptr();
A function object can be used as a wrapper, and it can call any type of functions. If you want to call a member function, the needed instance can for example be stored as a member. A lambda is a shorthand for creating such function object. Example:
auto lambda_free = [] {
free_function();
}
auto lambda_member = [f] {
f.member_function();
}
lambda_free();
lambda_member();
Type erasure techniques can be used to hide the type of various function objects, since they can be called in the exactly same manner. Standard comes with a template for such purpose: std::function. Example:
std::function<void()> fun_wrapper;
fun_wrapper = lambda_free;
fun_wrapper = lambda_member;
fun_wrapper = fun_ptr;
//fun_wrapper = mem_fun_ptr; // nope; there is no instance of foo
Pointers to free functions are very different from those that point to member functions. Not only is the syntax different, member function pointers also need a this first argument - the instance of their class they are supposed to operate on. You cannot use the same map to store both, if you intend to deal with raw (member) function pointers.
One solution is some kind of type erasure; you can store std::function objects in your map:
map<char, std::function<void()>>eventGroups;
void addSharedEvent(char groupIndex, const std::function<void()>& callback){ ... }
You can construct the parameter by plain function pointers, and in case of member functions usage of std::bind or a lambda.
Related
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 trying to implement more flexibility in my numerics by allowing me to choose different forms of a mathematical function and vary their parameters through instantiating them as objects of a certain class. That class includes certain mathematical functions I may choose plus parameters that I can vary. The constructor of the class sets a member function pointer in the class to a member function according to what mathematical function I want. I want to solely use the pointer to call whatever function it points to by directly using the pointer in my routine.
However, that proved daunting as I didn't know that member function pointers require a certain syntax and seem to work somewhat differently from regular function pointers according to what I could gather. I've experimented quite a bit and constructed myself a minimal example shared below.
#include<iostream>
#include<string.h>
#include<cstdlib>
#include<stdio.h>
class Someclass
{
public:
// constructor to set pointer
Someclass(std::string);
// member function pointer to hold functions
void (Someclass::*fptr)();
// auxiliary function to call testfunction via pointer
void call ();
// testfunction
void foo();
};
// testfunction
void Someclass::foo()
{
printf("foo says hi! \n");
}
// call via specific function
void Someclass::call()
{
(this->*fptr)();
}
// constructor
Someclass::Someclass(std::string name)
{
if(name=="foo")
{
this->fptr = &Someclass::foo;
}
}
int main()
{
Someclass someobject("foo");
someobject.foo(); // direct testfunction call: Works OK
someobject.call(); // call via auxiliary function: Works OK
//(someobject.*fptr)(); // direct pointer dereferencing: Gives Error
return(EXIT_SUCCESS);
}
It shows that I can access the pointer by use of another member function that just calls whatever the pointer points to via use of a this pointer. However, I still can't seem to get the function call to work if I try to use the pointer directly in my main function through the line,
(someobject.*fptr)()
This particular expression leads to my compiler complaining about the scope and if I include the class scope, the compiler mentions invalid use of non-static members. Still, I'm confused as to why my implementation here doesn't work and if it does, how the proper syntax in my problem would be and why that has to be so.
Any insights would be really appreciated.
fptr is a member of the object, not a variable local to main. In such respect member function pointers behave exactly the same as all other variable types. You were so close, and just need to qualify the function pointer name with the object name:
(someobject.*(someobject.fptr))();
The reasons for this is .* indicates a pointer to member function and does not directly reference the members of an object like the . and .-> operators. Since fptr is a member of Someclass and not a local variable you need to reference it directly like so
(someobject.*someobject.fptr)();
I don't understand why the following code compile and works:
template<typename Predicate>
void foo(Predicate p) {
}
bool g(int n) {
}
void user(int n) {
foo(g);
}
foo is supposed to get a function object that will run on a data structure but I made the method simpler, because what I don't understand is how can this works? A method isn't an object. The normal way to do it is to create a new class, override operator() and then send an instance of that class.
Well, in this case the Predicate parameter is substituted by a function pointer of type bool (*func) (int). Nothing wrong with that...
The Predicate template argument can be almost any type. So you can use it for function pointers and classes as well as the basic types.
If you use the function argument p as a function, then it can be anything that is callable, like a function pointer, an object whose class have an operator() member function, a pointer to a static member function, a std::bind object, a std::function object or a lambda expression.
It can't be a pointer to a member function though, because to call a pointer to a member function you need an instance to call it on. For this use std::bind.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to specify a pointer to an overloaded function?
I have a library which has a class defined as:
struct ClassA
{
static ClassA foo(long);
static ClassA foo(double);
}
I need to get the addresses of both of those functions. The code I am currently trying gives error C2440: cannot convert from 'overloaded-function' to '...'
ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;
I thought it might be the fact that they are static, but placing static either before or after the return type gives the same error.
The fact that the function is overloaded is not really relevant. The real issue here is the difference between a function-pointer and a member-function-pointer. I'll run through some examples without overloading.
Solution: Either remove the static, in order to define them as member-functions. Or else replace ns::ClassA::*ClassA_foo1 with *ClassA_foo1. I think you want the latter. (But I actually recommend you use typedef, as others have already suggested).
Consider these two:
namespace ns {
struct ClassA
{
static ClassA foo(long);
};
}
and
namespace ns {
struct ClassA
{
ClassA foo(long);
};
}
In the former case, foo is static and is therefore a typical function, and can be stored in a function-pointer:
ns::ClassA (ClassA_foo1)(long) = &ns::ClassA::foo;
If you remove the static, then it is not a function any more, it's a member function. And pointers-to-member-functions are different from pointers-to-functions, they must be executed with an object that will be the this object on which the method is called.
The type of a function pointer includes the type of the return value and the type of the parameters. But the type of a pointer-to-member-function must also include the type of the this object - you wouldn't expect to be able to run a method from a Circle on an object of type BankAccount.
Declaring a pointer-to-function:
ReturnType (*variable_name) (PARAM1, PARAM2)
Declaring a pointer-to-member-function:
ReturnType (ThisObjectType::*variable_name) (PARAM1, PARAM2)
This last line is the interesting one. At first glance, you might think that R (A::*v) (P1,P2) declares a normal function-pointer and places the resulting variable v into the A scope. But it does not. Instead it defines a pointer-to-member-function which operates on objects of type A.
The problem that you are observing has absolutely nothing to do with the fact that the function is overloaded. You'd get the same error for a non-overloaded function.
Static member functions have ordinary function type. Meanwhile, you are trying to interpret them as functions of member-function type. This leads to pointer type mismatch reported to you by the compiler. Here's a simple example that will fail to compile for the very same reason
struct S {
static void foo();
};
...
void (S::*p)() = &S::foo; // ERROR, pointer type mismatch
In other words, your pointers are declared as pointers of pointer-to-member-function type. Such pointers cannot hold the address of a static member function. A static member function and a non-static member function are beasts of completely different nature. The corresponding pointer types are not compatible and not convertible to each other. That's the reason for your error.
This is how it was probably supposed to look
ns::ClassA (*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (*ClassA_foo2)(double) = &ns::ClassA::foo;
i.e. the pointers on the left-hand side should be declared as ordinary function pointers, not as member function pointers.
ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;
It looks like you are trying to set the pair of static members ClassA_foo1 and ClassA_foo2 at file scope. If so, this is not valid syntax. The syntax for defining a static member is
SomeType ClassName::member = initializer;
It's best to use a typedef to declare and define ClassA_foo1 and ClassA_foo2:
struct ClassA {
typedef ClassA (*ClassALongGenerator) (long);
typedef ClassA (*ClassADoubleGenerator) (double);
static ClassALongGenerator ClassA_foo1;
static ClassADoubleGenerator ClassA_foo2;
};
then at file scope in some source file
ns::ClassALongGenerator ClassA_foo1 = ns::ClassA::foo;
ns::ClassADoubleGenerator ClassA_foo2 = ns::ClassA::foo;
i have made a sample example, in this i'm trying to pass a function as argument i am getting error, could you please help me
typedef void (*callbackptr)(int,int);
class Myfirst
{
public:
Myfirst();
~Myfirst();
void add(int i,callbackptr ptr)
{
ptr(i,3);
}
};
class Mysec
{
public:
Myfirst first_ptr;
Mysec();
~Mysec();
void TestCallback()
{
callbackptr pass_ptr = NULL;
pass_ptr = &Mysec::Testing;
first_ptr.add(2,&Mysec::Testing);
}
void Testing(int a,int b)
{
int c = a+b;
}
};
The type of the callback function you're passing as parameter is not defined as part of a class. You probably should define Testing as static.
You are geting an error because you are pointing to a member function. Pointers to member functions are different. See here:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1
A member function needs to know what instance it is working with (the this pointer) so it can't be called like any other function. If you moved the callback function out of the class (or made it static, which is similar to moving it out of the class) you could call it like any other function.
A more modern way of doing this is to use functors, e.g. boost::function and something like boost::bind :
C++ Functors - and their uses
how boost::function and boost::bind work
Those can hide the difference between member and global functions.
You are trying to access a member function pointer here, using a simple function pointer typedef, which will not work. Let me explain.
When you write a normal, non-member function (similar to C), the function's code actually exists in a location indicated by the name of the function - which you would pass to a function pointer parameter.
However, in the case of a member function, all you have is the class definition; you don't have the actual instance of the class allocated in memory yet. In such a function, since the this pointer is not yet defined, any reference to member variables wouldn't make sense, since the compiler doesn't have enough information to resolve their memory locations. In fact, member function pointers are not exact addresses; they encode more information than that (which may not be visible to you). For more, read Pointers to Member Functions.