How to invoke an object method passed to a variable?
class A {
public:
inline int f() {
return 1;
}
};
int main() {
A a;
int (A::*y)(); //'y' must be a method of 'A' class that returns 'int'
y = &A::f; //bind 'f' method
*y(); //how to invoke???
}
The other thread bound a method to an object field and it was invoked this way (a.*(a.x))(), but i can't find a way to do a similar thing to a simple variable.
Simply do (a.*y)();. You need the extra parantheses make the compiler resolve the pointer to member before making the function call. See operator precedence:
class A {
public:
inline int f() {
return 1;
}
};
int main() {
A a;
int (A::*y)(); //'y' must be a method of 'A' class that returns 'int'
y = &A::f; //bind 'f' method
(a.*y)();
}
Demo
Related
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
Is it possible to edit an object that has not yet been defined in a function? For example, if I had a class in one file that adds one to a number:
class MyClass
{
private:
int i;
public:
MyClass()
{
i = 0;
}
int addOne()
{
i += 1;
return i;
}
};
And in another file, the class is imported. When the add function is called it calls the addOne function from the class:
#include "MyClass.h"
void add()
{
a.addOne();
}
int main()
{
MyClass a;
add();
return 0;
}
When I compile this it returns the error
error: ‘a’ was not declared in this scope
Is there any way for this to work?
Sites I read but didn't help solve my problem:
http://www.cplusplus.com/forum/unices/21527/
When can I use a forward declaration?
https://en.wikipedia.org/wiki/Forward_declaration
Can we have functions inside functions?
What you want to do is something like this :
void add( MyClass & a)
{
int num = a.addOne();
}
int main()
{
MyClass newObj;
// passing the new object to add
add(newObj);
return 0;
}
The method add() has no idea about the "a" which you were trying to use and was therefore giving you an error.
The method addOne() has a return type of an int, so it is expected that when you use a method that returns a value, then you do something with it.
I found this question here but now I want to extend it. so I have the following class in one file and it works correctly:
typedef int (*fptr)();
int f1() {
return 1;
}
int f2() {
return 2;
}
fptr f( char c ) {
if ( c == '1' ) {
return f1;
}
else {
return f2;
}
}
But when I want to move the functions in another file and make a factory out of them, I get an error that I cannot understand.
it would be like this:
Header:
public class Factories{
public:
int f1();
int f2();
}
CPPFile:
int f1() {
return 1;
}
int f2() {
return 2;
}
Header:
public class FactoryClass{
public:
fptr f( char c );
}
CPPFile:
typedef int (*fptr)();
fptr f( char c ) {
if ( c == '1' ) {
return Factories::f1;
}
else {
return Factories::f2;
}
}
Here in the returns of this FactoryClass Function I get the error "return value type does not match the function type".
Any Ideas would be appreciated.
Factories::f1 is not a normal function, it is a member function. Since it is a member function it needs to take a pointer to the object that called it so it can affect that instance. This means the type of a member function includes what type of object it is called from so a pointer to f1 actually has the type
int (Factories::*)()
You will either have to make fptr
typedef int (Factories::*fptr)();
or make the functions static so they act like regular functions.
the member functions Facotires::f1 you are returning just have the wrong signature. If possible, make them (f1 and f2) static. If not, bind the respective class instance (using boost::bind or std::bind)
The function type changed when you put them in a class. The new type should be typedef int (Factories::*fptr)();
C++: Calling member function via pointer
I have a class MyClass. In it, I want to create an array of function pointer and initialize the array with the functions of another class (MemberClass).
MyClass has a pointer to MemberClass as member.
but I get this compile time error
error C2440: 'initializing' : cannot convert from 'void (__thiscall MyMemberClass::* )(void)' to 'F'
//This class has the function that I want to create a function pointer to
class MemberClass
{
private:
int myValue1;
int myValue2;
public:
int GetValue1() //I want to point to this function from a function pointer in another class
{
return myvalue1;
}
int GetValue2() //I want to point to this function from a function pointer in another class
{
return myvalue2;
}
}
//This has array of function pointer that I want to point to member function of another class
Class MyClass
{
typedef void(*F)();
private:
MemberClass* mclass;
F[] f;
Process();
}
.cpp
MyClass::MyClass()
{
f[2] = {&MemberClass::GetValue1, &MemberClass::GetValue2} //This line throws error
//error C2440: 'initializing' : cannot convert from 'void (__thiscall MyMemberClass::* )(void)' to 'F'
}
void MyClass::Processing()
{
//This is how I am hoping to use the function pointer array
F[Index]();
}
F is declared as pointer to function with no parameters returning void. But your functions return int, and are member functions of MemberClass rather than plain ordinary functions. So the type you need is
typedef int (MemberClass::*F)();
Calling it is also more interesting:
int result = (mclass->*f[index])();
Suggestion: rather than a method pointer, use C++11's functional library.
I'm butchering OP's sample code slightly to simplify the example.
MemberClass stays mostly the same. I removed the member variables because the methods are now hard-coded to return 1 and 2 to make them easy to tell apart.
#include <iostream>
#include <functional>
class MemberClass
{
public:
int GetValue1()
{
return 1;
}
int GetValue2()
{
return 2;
}
};
myClass gets a rip-up because this is where the action is.
class MyClass
{
private:
I'm using an array of std::function instead of a typedef and an array of the typedef. Note the template argument int(). This is an array of functions that takes nothing and returns an int. Magic in std::bind will provide the hidden this parameter required by methods. If the function has parameters that are not known at the time of binding, use std::placeholders to save room to them in the method's parameter list.
Since the methods are bound to their object, there is no longer any need to store MemberClass* mclass;
std::function<int()> f[2];
public:
Calling the function is simple: index the array and stick the brackets on.
int Process(int index)
{
return f[index]();
}
The constructor is either a bit trickier, or less tricky, depending on your school of thought. I'm using an initializer list because it is cleaner (to me, at anyrate) and often has performance advantages. For one thing, you can swap out the array for a std::vector or most other containers without having to change a line of code other than the variable definition.
f[0] = std::bind(&MemberClass::GetValue1, mem);
f[1] =...
inside the body of the constructor is still an option.
MyClass(MemberClass * mem):
f{std::bind(&MemberClass::GetValue1, mem),
std::bind(&MemberClass::GetValue2, mem)}
{
}
};
And a silly little bit of test code to make sure this all works. Why? Because every time you don't test code in it's simplest form you're taking an unnecessary risk. If it doesn't work small, it won't work big.
int main()
{
MemberClass c;
MyClass d(&c);
std::cout << d.Process(0) << std::endl;
std::cout << d.Process(1) << std::endl;
}
All together for one cut and paste-able block:
#include <iostream>
#include <functional>
class MemberClass
{
public:
int GetValue1()
{
return 1;
}
int GetValue2()
{
return 2;
}
};
class MyClass
{
private:
std::function<int()> f[2];
public:
int Process(int index)
{
return f[index]();
}
MyClass(MemberClass * mem):
f{std::bind(&MemberClass::GetValue1, mem),
std::bind(&MemberClass::GetValue2, mem)}
{
}
};
int main()
{
MemberClass c;
MyClass d(&c);
std::cout << d.Process(0) << std::endl;
std::cout << d.Process(1) << std::endl;
}
I've applied solutions based on some search made, but the problem still there. Thank you so much for the help.
error: must use '.*' or '->*' to call pointer-to-member function ...
source code:
#include <stdio.h>
class A
{
public:
struct data;
typedef int (A::*func_t)(data *);
typedef struct data
{
int i;
func_t func;
}
data;
data d;
void process()
{
d.func(&d);
}
A()
{
d.i = 999;
d.func = &A::print;
}
int print(data *d)
{
printf("%d\n", d->i);
return 0;
}
};
int main()
{
A *a = new A;
a->process();
return 0;
}
d.func(&d);
is not enough. func is a member-function-pointer which is pointing to a non-static member of A. So it can be invoked on an object of A. So you need to write this:
(this->*(d.func))(&d);
That would work as long as you write this inside A.
If you want to execute func from outside, say in main(), then the syntax is this:
A a;
(a.*(a.d.func))(&a.d);
That is an ugly syntax.
Your process function attempts to call d.func but it is a pointer to member function. A pointer to member function must be called on some object. Presumably you want the instance of A to be this, in which case your process function should look like:
void process()
{
(this->*(d.func))(&d);
}
Note the use of the ->* operator to call a member function when you have a pointer to it.
Other answers have already said you need to say (this->*d.func)(&d) to call a pointer-to-member function (because you need to provide the object that it's a member of)
Another option is to make the function a static function, which doesn't need special syntax to call. To do that, change the typedef like so:
typedef int (*func_t)(data *);
Then make the print function static:
static int print(data *d)
{
...
}
Now you can just call d.func(&d)
Unfortunately what you are trying to do will not be possible, the reason being that print is not a static member function. This means it expects an implicit first argument that is the this pointer.
I suggest you try using the std::function and std::bind function, something like this:
class A
{
struct data
{
std::function<void(const data&)> func;
int i;
};
data d;
public:
A()
{
d.func = std::bind(&A::print, *this);
d.i = 999;
}
void process()
{
d.func(d);
}
void print(const data& my_data)
{
std::cout << my_data.i << '\n';
}
};
Of course, since the print function now have a proper this pointer, you no longer need to pass the data structure to it:
class A
{
struct data
{
std::function<void()> func;
int i;
};
data d;
public:
A()
{
d.func = std::bind(&A::print, *this);
d.i = 999;
}
void process()
{
d.func();
}
void print()
{
std::cout << d.i << '\n';
}
};
Calling pointer the members require the class it is a member of to be the this param.
Try:
A a;
a.*(d.func)(&d);