Let's say I have the following definitions:
class ScriptInterpreter {
public:
class cell;
typedef ScriptInterpreter::cell (ScriptInterpreter::*proc_t) (const std::vector<cell> &);
class cell {
public:
proc_t proc;
};
ScriptInterpreter::cell proc_add(const std::vector<cell> & c);
};
And the following code going on:
ScriptInterpreter::eval(ScriptInterpreter::cell cell, environment * env)
{
// ...
ScriptInterpreter::cell c;
c.proc = &ScriptInterpreter::proc_add;
return (c.*proc_)(exps);
}
At the line where I try to call the function pointer I get the error
error: called object type 'proc_t' (aka 'ScriptInterpreter::cell (ScriptInterpreter::*)(const std::vector<cell> &)') is not
a function or function pointer
When I add the * in front of the func so the line looks like this:
ScriptInterpreter::cell c = (proc_cell.*proc_)(exps);
it produces this:
error: use of undeclared identifier 'proc_'
I already looked at Callback functions in c++ and other problems of that kind, but nothing really gave me a hint what's wrong or provided any information about my error. I definitely don't have any names twice or something of that kind.
Also after reading what is an undeclared identifier error and how do i fix it I'm pretty sure I got everything alright.
So what am I doing wrong?
Edit: updated the code with real code instead of placeholder code
In order to call a member function through a pointer of pointer-to-member type, you have to use either operator .* or operator ->*. And on the left-hand side you have to specify the object for which you want to invoke that member function.
In your case an attempt to do that could look as follows
A::B b_object;
b_object.func = &A::func_to_call;
A a_object;
A::B other_b_object = (a_object.*b_object.func)();
Note that since the pointer is declared as pointing to a member of A, the .* operator need an object of type A on the left-hand side.
However, in your specific case this is ill-formed since b_object.func is private and no accessible from main.
P.S. int main, not void main.
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.
Well,
I typedef function pointer as :
typedef string(*t_arr[5])();
and then i create function in class as :
void initStringFunctionPointer(t_arr t_err);
and then i declared as :
void Register::initStringFunctionPointer(t_arr t_err)
{
t_err[0] = &getName;
t_err[1] = &getSurname;
t_err[2] = &getUsername;
t_err[3] = &getPassword;
t_err[4] = &getEmail;
}
but all of lines gives this error :
C:\Qt Projects\base\ClassProject_tmp\goinlib.cpp:20: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&Register::getName' [-fpermissive]
t_err[0] = &getName;
^
I don't know what to do, Any ideas ?
Edit :
It worked, static or doing type is succeed, thank you.
It tells you right in the error message:
Say '&Register::getName'
Once you do this you will probably discover that it's illegal anyway because you can't store a pointer-to-member-function in a regular function pointer. You'll need to change your typedef therefore, or else make getName() and the rest static. To change the typedef, try this:
typedef string(Register::*t_arr[5])();
Hopefully that's right, the array thing makes me a little uncertain; you might consider keeping the array part out of the basic typedef and adding it on elsewhere (on a second typedef or at the place of use).
I'm new to c++ . I want to know about object pointer and pointer to member function . I wrote a code which is following:
code :
#include <iostream>
using namespace std;
class golu
{
int i;
public:
void man()
{
cout<<"\ntry to learn \n";
}
};
int main()
{
golu m, *n;
void golu:: *t =&golu::man(); //making pointer to member function
n=&m;//confused is it object pointer
n->*t();
}
but when i compile it it shows me two error which is following:
pcc.cpp: In function ‘int main()’:
pcc.cpp:15: error: cannot declare pointer to ‘void’ member
pcc.cpp:15: error: cannot call member function ‘void golu::man()’ without object
pcc.cpp:18: error: ‘t’ cannot be used as a function.
my question are following :
What I'm doing wrong in this code ?
How to make object pointer ?
How to make pointer to member function of a class and how to use them ?
Please explain me these concept.
Two errors corrected here:
int main()
{
golu m, *n;
void (golu::*t)() =&golu::man;
n=&m;
(n->*t)();
}
you want a pointer to function
the priority of the operators is not the one you expected, I had to add parenthesis. n->*t(); is interpreted as (n->*(t())) while you want (n->*t)();
A member function pointer has the following form:
R (C::*Name)(Args...)
Where R is the return type, C is the class type and Args... are any possible parameters to the function (or none).
With that knowledge, your pointer should look like this:
void (golu::*t)() = &golu::man;
Note the missing () after the member function. That would try to call the member function pointer you just got and thats not possible without an object.
Now, that gets much more readable with a simple typedef:
typedef void (golu::*golu_memfun)();
golu_memfun t = &golu::man;
Finally, you don't need a pointer to an object to use member functions, but you need parenthesis:
golu m;
typedef void (golu::*golu_memfun)();
golu_memfun t = &golu::man;
(m.*t)();
The parenthesis are important because the () operator (function call) has a higher priority (also called precedence) than the .* (and ->*) operator.
'void golu:: *t =&golu::man();' should be changed to 'void (golu:: *t)() =&golu::man;' you are trying to use pointer to function not pointer to result of a static function!
(1) Function pointer is not declared properly.
(2) You should declare like this:
void (golu::*t) () = &golu::man;
(3) Member function pointer should be used with object of the 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.
#include<iostream>
class name
{
public:
int a;
name():a(0){};
};
void add(name * pname)
{
pname = NULL;
}
int main()
{
name varName();
name * pName = new name();
add(pName);
add(&varName);//error C2664: 'add' : cannot convert parameter 1 from 'name __cdecl *)(void)' to 'name *'
}
The error is on the first line of the main function:
name varName();
You are not creating an instance of class name with the default constructor, you are actually declaring a new function called varName, with no parameters, which returns a name instance.
You should instead write:
name varName;
I think it's worth telling you about a similar problem, that also causes trouble:
struct foo { };
struct bar { bar(foo f); };
int main() {
// does *not* create a bar object initialized by a default constructed
// foo object.
bar b(foo());
}
What b really is is a function that returns a bar and takes as first argument a pointer to a function that returns a foo taking no arguments. It's the same as:
bar b(foo(*)());
If you want to create a bar object initialized by a default constructed foo, put parentheses around the argument. That makes it doesn't look like a function declaration anymore, and the compiler will interpret it like you want:
bar b((foo()));
There are also non-obvious cases where a compiler error should be risen. GCC gets this wrong, but Comeau gets it right again. Consider the following snippet
struct foo {
static bool const value = false;
};
int main() {
int v(int(foo::value));
}
You will probably expect that this takes the static constant, and casts it to int, initializing the v variable to 0? No, it won't according to the Standard, because the initializer can be interpreted as a declaration, according to pure syntax analysis, as the following shows
struct foo {
static int value;
};
// valid, parentheses are redundant! Defines `foo::value`.
int (foo::value);
Whenever the initializer can be interpreted as a declaration, in such a situation whole the declaration will declare a function. So, the line in main declares a function like the following, omitting the redundant and meaningless parentheses
int v(int foo::value);
And this will cause a compiler error when parsing the function declaration, because a function parameter name may not be qualified.
It's also worth noting that your add() function doesn't have any lasting effects -- all it's doing is assigning a value to pname, which is a copy of the pointer you pass into it. If you want to actually have that assignment stick, you would need to pass the pointer by reference as "name*& pname".
name varName();
is interpreted as a local function declaration. To invoke the default constructor, use
name varName;
instead. Most vexing, yes.