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;
Related
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.
I have a C library with a struct like this:
struct A {
void process(){
doProcess();
};
void (*doProcess)(void);
}
Now, I have a class like
class B
{
public:
B(): a(){
a.doProcess = print();
}
void print(){
// do anything
}
private:
A a;
}
This cannot work since print is a member function and has to be called on an object of B.
Thus I tried to use the boost::bind function:
a.doProcess = boost::bind(&A::print, this)
This does not work either.
I also tried to modify the C Library and replace the function pointer definition with a boost::function definition. But then the compiler complains about not finding "" which is included in "boost/function.h".
Is there a (easy/boost) way of assigning a member function to the struct's pointer?
You simply cannot do this. Member functions have an implicit this argument that is a pointer to the object on which the function is being called. A function that does not take a B* as an argument will never manage to run on a specific B instance and a function that does not take this point as its first argument can never have the same signature as a class method. For more details on this problem and an example of a workaround read:
https://isocpp.org/wiki/faq/pointers-to-members#memfnptr-vs-fnptr
Pay attention to the note at the bottom of the answer on how static member functions can be used in such manner.
Pure C++ projects can use std::function & std::bind to achieve what you are asking about, but a C library used by a C++ project cannot work with these types.
//mediafactory.h
class MediaFactory{
public:
typedef Media* (*funPointer)();
funPointer somePointer;
}
//mediafactory.cpp
Media* MediaFactory::returnMedia(){
}
when I try to do
somePointer = returnMedia;
I get this error:
1 IntelliSense: a value of type "Media *(MediaFactory::*)()" cannot be assigned to an entity of type "MediaFactory::funPointer" c:\Users\...\mediafactory.cpp 37
However, if i change the function to the code below, it will compile and work
Media* returnMedia(){ //without scope
}
MediaFactory::returnMedia() is a non-static member function, and can only be called via an instance of MediaFactory.
typedef Media* (*funPointer)(); defines a pointer to a static or non-member function, which is called without any object. It's therefore a different type, incompatible with a pointer to a member function.
If you don't need it to point to a member function, then make returnMedia() either static or a non-member (as you note in at the end of the question).
If you do need it to point to a member function, then you need a pointer-to-member:
typedef Media* (MediaFactory::*funPointer)();
which can be set to point to a member function:
somePointer = &MediaFactory::returnMedia;
and can be called on a factory object:
Media * media = (someFactory.*somePointer)();
Alternatively, you might want to bind the function pointer to an object when you set the pointer, rather than when you use it. In this case, you could use std::function (or boost::function if you're stuck with an outdated compiler) to store an arbitrary callable object:
typedef std::function<Media*()> function;
function someFunction;
someFunction = std::bind(&MediaFactory::returnMedia, &someFactory);
Media * media = someFunction();
You cannot assign a method of a class to a global function pointer without an instance of this class.
I have my code organized as following
class MyClass
{
public:
typedef void (MyClass::Ptr2func)();
}
struct abc
{
MyClass::Ptr2func ptr;
bool result;
}
void main()
{
MyClass myCls;
abc var;
//here is a lot of decision making code and pointer initializations
//I want to copy the pointer to function in another variable
MyClass::Ptr2func tempPtr;
tempPtr=var.ptr;
}
When I try to copy the var.ptr into tempPtr it gives me a compilation error that the argument list is missing. Also it gives me compilation error on myCls.*(var.ptr()); Is there a precedence issue? I have tried using parenthesis but nothing works. I hope someone can help me out on this.
Thanks and regards,
Saba Taseer
I believe that the problem is that your typedef
typedef void (MyClass::Ptr2func)();
Is not defining a typedef for a pointer to member function, but for a member function type. The typedef for a member function pointer would be
typedef void (MyClass::* Ptr2func)();
Notice the explicit pointer involved here. The type
typedef void (MyClass::Ptr2func)();
is actually a typedef for the type of a member function inside of MyClass that takes no arguments and returns void.
As for your final question, the proper syntax for calling a pointer to a member function is (I believe)
(myCls.*var.ptr)()
Notice that you must parenthesize the expression (myClass.*var.ptr) before trying to call it as a function, since the code
myCls.*(var.ptr())
Means "dereference the pointer-to-member returned by var.ptr() relative to object myCls.
Hope this helps!
This:
typedef void (MyClass::Ptr2func)();
defines a function type. The MyClass:: is completely extraneous in that definition; the final type is void (). (Why? You're in MyClass, so MyClass:: is treated as reinforcement that you want the typedef Ptr2func to belong to MyClass, not as a statement that you want the type to designate a member function.)
You want this:
typedef void (MyClass::*Ptr2func)();
which defines a pointer to a member function.
You're asking about compilation errors.
As I'm writing this your code does not have semicolong after each class definition.
Also, just about any other compiler than MSVC will react to void main; use standard int main.
As an utter beginner (making those kinds of mistakes) it's not a good idea to use member pointer.
Simply don't, but instead explain what you hoped to achieve by that.
Cheers & hth.
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.