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.
Related
I've been racking my brain over getting the syntax right on declaring, defining and finally calling a member function pointer inside my program.
I'm writing a window manager with Xlib, and am trying to enable the user to define all key bindings in a vector of Keybinds. The Keybind struct contains more member variables, which I have left out here for the sake of brevity.
Here's what I've got so far.
Keybind, a struct containing a member variable, func, that points to a MyClass member function.
struct MyBind {
MyBind(void (MyClass::*_func)(const XKeyEvent&))
: func(_func) {}
void (MyClass::*func)(const XKeyEvent&);
}
Declaration and populating of a vector that holds user-defined Keybinds.
// in my_class.hh
std::vector<MyBind*> my_binds_;
// in my_class.cc, constructor
my_binds_.push_back(new MyBind( &MyClass::do_this ));
my_binds_.push_back(new MyBind( &MyClass::do_that ));
At this point, everything compiles and runs.
Now, when I try to delegate work by iterating over the my_binds_ vector, things go wrong. It is worth noting that I've left out error handling and other member variable accesses for clarity.
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(my_bind->*func)(e); // erroneous line
}
}
This should be the correct syntax, but it fails to compile, stating error: ‘func’ was not declared in this scope (g++, similar error from clang++).
This is weird to me, as replacing the erroneous line of code with auto test = keybind->func; does compile.
What am I doing wrong? Is there a better way to handle user key bind definitions? Thanks!
It would be best to use std::function and forget about raw member-function pointers altogether. They will only bring you pain :)
The problem with you code is that you only have a pointer to a method but no object. Your bind struct should also store an object pointer to call the method on:
struct MyBind {
MyBind(MyClass *obj, void (MyClass::*_func)(const XKeyEvent&))
: obj(obj), func(_func) {}
MyClass *obj;
void (MyClass::*func)(const XKeyEvent&);
void operator()(const XKeyEvent& event) const
{
(obj->*func)(event);
}
}
And then use it like this:
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(*my_bind)();
}
}
I've added a call operator to the bind struct for convenience. Note that the ->* operator is applied to the object the method belongs to.
This is not an answer, rather a pointer to your answer or my so-question :)
You had to use
(this->*(my_bind->func))(e);
instead of:
(my_bind->*func)(e);
I have re-created your error msg and asked a question after many different attempts.
See this( pointer to your answer ;) ): How to call pointer to member function, which has been saved in a vector of custom struct?
MyBind holds the pointer to member function of some instance of MyClass. Therefore in order to call these function pointers, you need to explicitly tell using this keyword, for which instance of MyClass you want the func to be called.
This is probably something elementary, I have a function from one class (called cell) with identifier woo_func_ptr taking a pointer to function of type void with no arguments (void (*void_ptr)(void)) (which I typedef). In another class, I have an object of cell and I use the method woo_func_ptr. It won't allow me to, I get the error in the above title. If these two functions were not embedded inside a class, they would work fine
typedef void (*void_ptr)(void);
double WOO{0};
struct cell {
void woo_func_ptr(void_ptr jo)
{
jo();
}
};
class woosah
{
public:
void woo_func()
{
WOO+=rand();
std::cout << WOO << std::endl;
};
void run()
{
// other stuff
temp_cell.woo_func_ptr(woo_func);
// yet more stuff
}
cell temp_cell;
};
First of all pointer to woosah member function should be declared as
typedef void (woosah::*void_ptr)(void);
and then compiler would complain that it needs to see woosah definition while parsing this statement.
If you let compiler parse class woosah first by moving it up then it will complain that type cell is not defined (since it is contained within woosah). That wil still not solve your problem because of cyclic dependency while parsing.
One way is to solve cyclic dependency is by making temp_cell a pointer to cell instance and have it contained within woosah.
Also note, the syntax to call member function is by using .* or ->*
void run()
{
// other stuff
temp_cell->woo_func_ptr(temp_cell->*woo_func); // assuming temp_cell is pointer to some cell instance
// yet more stuff
}
http://msdn.microsoft.com/en-us/library/b0x1aatf(v=vs.80).aspx shows similar errors and their fixes.
A member function is not like a regular function. That's why there's a seperate "pointer to member function" type. It's because member functions are passed the implicit this pointer.
In fact, the standard even limits (severly) the casting of pointer to member function.
That's the source of your error.
You could use a static class function...
Change
void woo_func()
to
static void woo_func()
This will of coarse may not be what you want if you are trying to access data members of a particular object.
Member functions are kind of special and should not be treated as normal functions.
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.
Here is an example of what I want to accomplish and how:
class MyClass
{
public:
void Dummy() const{}
};
typedef void (MyClass::*MemFunc)();
void (const MyClass * instance)
{
MemFunc func=&MyClass::Dummy;
// (instance->*func)(); //gives an error
(const_cast<MyClass *>instance->*func)(); // works
}
Why do compilers (gcc 3 & 4) insist that instance should be non-const? Would that const_cast cause issues?
FYI: instance` is not necessarily const, I just don't want a callee to mess with it.
What is happening here?
The error is in the line before. Change the typedef to
typedef void (MyClass::*MemFunc)() const;
To make it a pointer to a const member function type.
The difference might be more clear when considering this code and how it works:
typedef void FunctionType() const;
typedef FunctionType MyClass::*MemFunc;
A member-function pointer in particular is actually just a special case of a member-pointer in general. For a const member function, the function type of the member function is different than for a non-const member function. That is why the types have to match.
typedef void (MyClass::*MemFunc)();
Here you are defining a pointer to a function which might modify its object.
MemFunc func=&MyClass::Dummy;
Here you are assigning a function which won't change it's object to such a pointer. This is legal, since not changing is a subset of might change.
(instance->*func)();
Here you are trying to call a function which might change its object, using an object which cannot be changed.
You will need to change the definition of MemFunc