For one class I want to store some function pointers to member functions of another class. I am trying to return a class member function pointer. Is it possibile?
class one{
public:
void x();
void y();
};
typedef void(one::*PF)(void);
class two :public one{
public:
virtual PF getOneMethodPointer();
};
class three : public two{
std::vector<PF> pointer_to_function;
PF getOneMethodPointer();
pointer_to_function.push_back(getOneMethodPointer())? //how to get method x from class one?
};
In C++11/14, you can always use std::function wrapper to avoid writing unreadable and old C-style function pointers. Here's a simple program with this approach:
#include <iostream>
#include <functional>
using namespace std;
class one {
public:
void x() { cout << "X called" << endl; }
function<void()> getOneMethodPointer();
};
class two : public one {
public:
function<void()> getOneMethodPointer() {
return bind(&one::x, this);
}
};
int main()
{
two* t = new two();
t->getOneMethodPointer()();
delete t;
return 0;
}
As you can see, there's also std::bind used to bind method with std::function. First argument is a reference to the x() method and the second one specifies to which concrete (instantiated) object the pointer is meant to point. Note, that if you say to the st::bind "hey, bind me x() method from one class", it still doesn't know where it is. It knows that - for instance - x() method in this object can be found 20 bytes next to its beginning. Only when you add that it is from for example two* t; object, the std::bind is able to locate the method.
EDIT: Answering to your questions in comments: below code shows an example with virtual getMethodPointer() method:
#include <iostream>
#include <functional>
using namespace std;
class one {
public:
void x() { cout << "X called (bound in one class)" << endl; }
void y() { cout << "Y called (bound in two class)" << endl; }
virtual function<void()> getMethodPointer() {
return bind(&one::x, this);
}
};
class two : public one {
public:
virtual function<void()> getMethodPointer() {
return bind(&one::y, this);
}
};
int main()
{
one* t_one = new one();
one* t_two = new two();
t_one->getMethodPointer()();
t_two->getMethodPointer()();
delete t_one;
delete t_two;
return 0;
}
The C++ syntax for it is this:
class two: public one{
virtual PF getOneMethodPointer(){
return &one::x;
}
};
[Live example]
Related
Following up my previous question about pointers to functions I'd like to ask, what is the difference between the pieces of code below.
This works! I use a pointer to a member function of the class Base. Though I have to call the function through the pointer differently cause it's a pointer to a member and not a pointer to a free function. But it works.
#include <iostream>
class Base;
using Handler = void (Base::*)(int e);
class Base
{
protected:
Base(Handler init)
{
currentState = init;
}
Handler currentState;
};
class Derived : public Base
{
public:
Derived() : Base((Handler)&foo)
{
}
void run(int e)
{
(this->*currentState)(e);
}
private:
void foo(int e)
{
std::cout << "foo function\n";
std::cout << "e = " << e << std::endl;
}
};
int main(void)
{
Derived derived;
derived.run(10);
return 0;
}
Output:
foo function
e = 10
Then I modify the code a little bit and I use pointer to function using Handler = void (*)(int e);
#include <iostream>
class Base;
using Handler = void (*)(int e);
class Base
{
protected:
Base(Handler init)
{
currentState = init;
}
Handler currentState;
};
class Derived : public Base
{
public:
Derived() : Base((Handler)&foo)
{
}
void run(int e)
{
currentState(e);
}
private:
void foo(int e)
{
std::cout << "foo function\n";
std::cout << "e = " << e << std::endl;
}
};
int main(void)
{
Derived derived;
derived.run(10);
return 0;
}
And it does not work, as you can see from the output below
Output:
foo function
e = 679096448
Also, Is that legal in C++? Or I have a piece of code that happens to work? I'm asking that because I'm making a state machine model and I wouldn't like surprises in the middle of development down the line...
EDIT: Adding one more question, Why does the function is called, but the argument value is unspecified?
I think you should use std::function and learn how to use lambdas or std::bind -- I prefer lambdas.
You can define something like this:
#include <functional>
using Comparator = std::function<bool(const MyObject &)>;
And then you can assign a lot of different things to it. You can define either free or static methods. You can use std::bind in order to assign non-static methods. Or you can do what I do, and use a lambda.
void foo(Comparator f) {
if (f(someObject)) {
....
}
}
That part is easy. You can call that like this (for instance):
foo([](const Myobject &obj) { return obj.foo == bar; });
Or:
foo([](const Myobject &obj) { return obj.gleep(); });
Function pointers are a C-ism. std::function is how to do it in C++. It's more powerful. It can do everything a function pointer can do, but it can go further.
I don't care for std::bind, but you can find examples. Lambda syntax isn't necessarily simple, either, but I prefer it.
I struggle creating derived classes and passing method pointers from it to the base class, so that a function declared in the base class may call it (call the function of the derived class via interface).
The goal is to create derived classes to bring their own ressources and functions, but the call of a function declared there should be possible by calling one of them in the function the base class provides. For this i need to pass a member function pointer of the derived down to the base class.
Here's what I tried:
class KeyFunction
{
void(*KeyFunction::KeyFuncPtr)() = nullptr; //pointer to a method of this class to store standard behavior for call
public:
KeyFunction(void(*KeyFunction::KeyFunc)()) : KeyFuncPtr(KeyFunc) {} //constructor which takes in standard behavior
void func() //standard call of the function
{
if(KeyFuncPtr)KeyFuncPtr(); //call with ensurance there's something to be called
}
void operator()() //make KeyFunction class callable
{
func();
}
};
class customRessource{
public:
string up = "UP";
string down = "DOWN";
};
class customKeyFunc : public KeyFunction
{
customRessource& r;
public:
void moveup() //possible behavior
{
cout << r.up;
}
void movedown()
{
cout << r.down;
}
customKeyFunc( void(*customKeyFunc::KeyFunc)() ) :KeyFunction( ( void(*KeyFunction::)() ) (KeyFunc) ){}
};
int main()
{
customKeyFunc Up(&(customKeyFunc::moveup)); //setup functions
customKeyFunc Down(&customKeyFunc::movedown);
Up(); //call functions
Down();
getchar();
return 0;
}
The main function at the end shows the supposed way to use the class .
First of all: my types in the constructors of each class go wild (i tried a lot of search about how to write member pointers right but i'm still not stable with the syntax)
Can someone help me get them right ?
Can I even do this (especially casting down member pointers like i did in the customKeyFunc constructor)? Am I aproaching this the right way or do I think too complicated ?
Thank you in advance for your help !
something like this?
#include <functional>
#include <string>
#include <iostream>
class customResource{
public:
const std::string up = "UP";
const std::string down = "DOWN";
};
class customKeyFunc
{
const customResource& r;
public:
customKeyFunc(const customResource& r) : r(r) {}
void moveup() //possible behavior
{
std::cout << r.up;
}
void movedown()
{
std::cout << r.down;
}
};
int main()
{
customResource r;
customKeyFunc f(r);
auto Up = std::function<void()>(std::bind(&customKeyFunc::moveup, f));
auto Down = std::function<void()>(std::bind(&customKeyFunc::movedown, f));
Up(); //call functions
Down();
return 0;
}
std::function<void()> is a polymorphic functor which will copy any object that:
is movable or copyable, and
implements void operator()
I have 2 class, I would like to pass a method from one to other by callback!
See that I also wish to hold the address of this method using void (*callBack)();
I'm used to do this in C, but I dont know how to do this in c++;
#include <iostream>
using namespace std;
class A
{
private:
void (*callBack)(); //to hold the address of the method
public:
A();
void setCallBack(void(*cB)());
void useCallBack();
};
A::A()
{
}
void A::setCallBack(void(*cB)())
{
callBack = cB;
}
void A::useCallBack()
{
callBack();
}
class B
{
private:
A * Aguy;
public:
B();
void someMethod();
void otherMethod();
};
B::B()
{
Aguy = new A();
}
void B::otherMethod()
{
Aguy->setCallBack(someMethod);
Aguy->useCallBack()
}
void B::someMethod()
{
cout << "Hello. I'm from class b" << endl;
}
int main()
{
B Bguy;
Bguy.otherMethod();
return 0;
}
The problem is that:
void (*callBack)();
This is not a pointer to a method. This is a pointer to a function.
To have a pointer to a method you need to specify the class the method is in.
void (B::*callBack)();
Then when you call it you need to call it via an object.
void A::useCallBack(B* b)
{
(b->*callBack)();
}
But this is probably not what you want.
What you really want is a wrapper that encapsulates all this.
I would take a look at std::function. This will allow you to wrap a method call and an object into a single object that you can then call.
std::function<void()> callback;
Just replace all your occurrences of void(*cB)() with std::function<void()> then you can bind an instance of the object to the method at the call point.
Aguy->setCallBack(std::bind(&B::someMethod, this));
This also allows you to seemly pass any normal function or functor as a callback.
void print()
{ std:cout << "It worked\n";
}
...
Aguy->setCallBack(&print);
struct Printer
{
void operator()() const
{
std::cout << "It worked with obejct\n";
}
}
...
Aguy->setCallBack(Printer());
If you need to pass member function pointers see the modified code. it uses modern c++ constructs.
#include <iostream>
#include <functional>
using namespace std;
class A
{
private:
typedef std::function<void()> some_void_function_type;
some_void_function_type f_;
public:
A();
void setCallBack(some_void_function_type f);
void useCallBack();
};
A::A()
{
}
void A::setCallBack(some_void_function_type f)
{
f_ = f;
}
void A::useCallBack()
{
f_();
}
class B
{
private:
A * Aguy;
public:
B();
void someMethod();
void otherMethod();
};
B::B()
{
Aguy = new A();
}
void B::otherMethod()
{
Aguy->setCallBack(std::bind(&B::someMethod, this));
Aguy->useCallBack();
}
void B::someMethod()
{
cout << "Hello. I'm from class b" << endl;
}
int main()
{
B Bguy;
Bguy.otherMethod();
return 0;
}
See c++ - <unresolved overloaded function type> for details.
To quote the answer:
In C++, member functions have an implicit parameter which points to
the object (the this pointer inside the member function). Normal C
functions can be thought of as having a different calling convention
from member functions, so the types of their pointers
(pointer-to-member-function vs pointer-to-function) are different and
incompatible. C++ introduces a new type of pointer, called a
pointer-to-member, which can be invoked only by providing an object.
Put static on someMethod:
class B
{
private:
A * Aguy;
public:
B();
static void someMethod();
void otherMethod();
};
void B::otherMethod() {
Aguy->setCallBack(B::someMethod);
Aguy->useCallBack(); // adding missing semicolon
}
Is it possible in C++?
For example I have a pointer to a function that takes no parameters and its return type is void:
void (*f)();
and and a function object:
class A
{
public:
void operator()() { cout << "functor\n"; }
};
Is it possible to assign to f the address of an A object? And when I call f() to call the A functor?
I tried this but it doesn't work:
#include <iostream>
using namespace std;
class A
{
public:
void operator()() { cout << "functorA\n"; }
};
int main()
{
A ob;
ob();
void (*f)();
f = &ob;
f(); // Call ob();
return 0;
}
I get C:\Users\iuliuh\QtTests\functor_test\main.cpp:15: error: C2440: '=' : cannot convert from 'A *' to 'void (__cdecl *)(void)'
There is no context in which this conversion is possible
Is there any way to achieve this?
You can't do it in the way you've specified, because:
operator() must be a nonstatic function (standards requirement)
a pointer to a non-static function must have an implicit parameter - the pointer to the class instance
your call to f() does not give any indication on which instance of the object A your function is called
Using C++11 and std::function, as Stephane Rolland pointed out, may do the trick - you'll be specifying the pointer to the object in the binding:
std::function<void(void)> f = std::bind(&A::operator(), &ob);
(See question on using std::function on member functions)
If you use C++11, could use std::function
#include <functional>
std::function<void()> f;
int main()
{
A ob;
ob();
f = ob; // f refers to ob
f(); // Call ob();
return 0;
}
Yes it's kind of possible using a C++1/C++0x feature, but to achieve this you should use the std::function which can address to the two types, functions and object functions.
#include <functional>
class A
{
public:
void operator()() { }
};
int main()
{
std::function<void(void)> aFunction;
A ob;
aFunction = ob;
// or as another user said
// aFunction = std::bind(&A:operator(), &ob);
aFunction();
void (*f)();
aFunction = f;
aFunction();
return 0;
}
and if you're stuck with C++03, you could play with std::mem_fun and std::ptr_fun
How about some workaround like this:
Basically you want to have a common way of calling member functions and functions. Then maybe you could create a wrapper that would represent a generic pointer to either a function or member function. Let's say you have Base class and you want to be able to invoke operator() of all derived classes. Then you also have a function() that you want to invoke as well:
class Base
{
public:
virtual void operator()() = 0;
};
class A : public Base
{
public:
void operator()(){ std::cout << "A()" << std::endl; }
};
void function()
{
std::cout << "function" << std::endl;
}
If you create an wrapper that allows you to construct your custom pointer (MyFncPtr):
typedef void (Base::*BaseFncPtr)();
typedef void (*FncPtr)();
class MyFncPtr
{
public:
MyFncPtr(FncPtr f) : fnc(f), baseObj(NULL), baseFnc(NULL) { }
MyFncPtr(BaseFncPtr fPtr, Base* objPtr) : baseFnc(fPtr), baseObj(objPtr), fnc(NULL) { }
void invoke()
{
if (baseObj && baseFnc)
(baseObj->*baseFnc)();
else if (fnc)
fnc();
}
private:
BaseFncPtr baseFnc;
Base* baseObj;
FncPtr fnc;
};
you could achieve it like this:
A a;
MyFncPtr myPtr(&Base::operator(), &a);
myPtr.invoke();
MyFncPtr myPtr2(function);
myPtr2.invoke();
outputs:
A()
function
Hope this helps :)
The code snippet below produces an error:
#include <iostream>
using namespace std;
class A
{
public:
virtual void print() = 0;
};
void test(A x) // ERROR: Abstract class cannot be a parameter type
{
cout << "Hello" << endl;
}
Is there a solution/workaround for this error other/better than replacing
virtual void print() = 0;
with
virtual void print() = { }
EDIT: I want to be able to pass any class extending/implementing the base class A as parameter by using polymorphism (i.e. A* x = new B() ; test(x); )
Cheers
Since you cannot instantiate an abstract class, passing one by value is almost certainly an error; you need to pass it by pointer or by reference:
void test(A& x) ...
or
void test(A* x) ...
Passing by value will result in object slicing, with is nearly guaranteed to have unexpected (in a bad way) consequences, so the compiler flags it as an error.
Of course, change the signature:
void test(A& x)
//or
void test(const A& x)
//or
void test(A* x)
The reason your version doesn't work is because an object of type A doesn't logically make sense. It's abstract. Passing a reference or pointer goes around this because the actual type passed as parameter is not A, but an implementing class of A (derived concrete class).
To be absolutely clear, the problem is, whenever you define a class:
#include <iostream>
class foo {
public:
char *name = (char *)"foo";
};
and pass an instance of that class to a function, it creates a copy:
void bar(foo a) {
a.name = (char *)"bar";
}
int main() {
foo x;
bar(x);
std::cout << x.name << std::endl; // foo
return 0;
}
With regard to inheritance, it creates a copy as an instance of the base class:
#include <iostream>
class foo {
public:
char *name = (char *)"foo";
};
class bar: public foo {
public:
char *name = (char *)"bar";
};
void baz(foo a) {
std::cout << a.name << std::endl;
}
int main() {
bar x;
baz(x); // again, foo
return 0;
}
so, by doing
void baz(AbstractType a) {
...
}
you're telling the compiler to copy an AbstractType as an instance of AbstractType itself, which is illegal.
Pass it as const AbstractType &a to prevent copying.