My problem is about passing a member function from a Class A, to a member function of a Class B:
I tried something like this :
typedef void (moteurGraphique::* f)(Sprite);
f draw =&moteurGraphique::drawSprite;
defaultScene.boucle(draw);
moteurGraphique is A class, moteurGraphique::drawSprite is A member function,
defaultScene is an instance of B class, and boucle is B member function.
All that is called in a member function of A:
void moteurGraphique::drawMyThings()
I tried different ways to do it, that one seems the more logical to me, but it won't work!
I got:
Run-Time Check Failure #3 - The variable 'f' is being used without being initialized.
I think I am doing something wrong, can someone explain my mistake ?
C++11 way:
using Function = std::function<void (Sprite)>;
void B::boucle(Function func);
...
A a;
B b;
b.boucle(std::bind(&A::drawSprite, &a, std::placeholders::_1));
Member functions need to be called on objects, so passing the function pointer alone is not enough, you also need the object to call that pointer on. You can either store that object in the class that is going to call the function, create it right before calling the function, or pass it along with the function pointer.
class Foo
{
public:
void foo()
{
std::cout << "foo" << std::endl;
}
};
class Bar
{
public:
void bar(Foo * obj, void(Foo::*func)(void))
{
(obj->*func)();
}
};
int main()
{
Foo f;
Bar b;
b.bar(&f, &Foo::foo);//output: foo
}
Can't you make drawMyThing a static function if you don't need to instantiate A, and then do something like :
defaultScene.boucle(A.drawMyThing(mySpriteThing));
?
Related
I'm thinking of the way how to call most base virtual function given a pointer to a base class and pointer to most base virtual function of that class. This call should happen in outher module, e.g. Invoker, this module shouldn't know anything about class and function it's calling.
Need to build event-emitting system that will not respect virtuality of the callbacks and call exactly that target's function which address was passed to Invoker.
I want to make mandatory for derived classes to use their own callbacks and subscriptions and in general don't do virtual callback in the hierachy. If client still needs something alike, he can try to use virtual handlers in non-virtual callback of the base class.
I tried all kind of casts. Doesn't help, maybe I use them wrong...
#include <iostream>
class A
{
public:
virtual void Foobar() { std::cout << "A" << std::endl; }
};
class B : public A
{
public:
virtual void Foobar() { std::cout << "B" << std::endl; }
};
using CallbackType = void(A::*)();
void Invoker(A* target, CallbackType function)
{
(target->*function)();
}
int main()
{
A a;
B b;
Invoker(&a, &A::Foobar);
Invoker(&b, &A::Foobar);
b.A::Foobar(); // how to make similar call inside Invoker(&b, &A::Foobar) ?
return 0;
}
The output will be:
A
B
A
I want Invoker somehow to call the most base function, so expected output is:
A
A
A
It's not possible to do this with a pointer to member function. Instead, a lambda would be more appropriate:
Invoker(&b, [](A& a) { a.A::Foobar(); });
You need to rewrite Invoker as a template so that it can accept both lambdas and pointers to members:
template <class F>
void Invoker(A* target, F&& function) {
std::invoke(std::forward<F>(function), *target);
}
From what I know, it's impossible.
You can't call a virtual function in a non-virtual manner through a member function pointer.
Well, the lambda solution presented in the other answer is indeed the way to go.
However, I found a way to do what you want ... sort of. The downside is that it involves a slicing copy of the object:
void Invoker(A* target, CallbackType function)
{
(static_cast<A>(*target).*function)();
}
or
void Invoker(A target, CallbackType function)
{
(target.*function)();
}
I have a method that is invoked a lot in my code with this signature:
void foo (std::function<void(int)> func, int a) {
func(a);
}
I can easily pass a function like this to the method:
static void bar(int a);
foo(bar, 42)
Also, if I have a class instance, I can pass my the function pointer to my instance roughly like this ugly snippet:
class Baz {
bar(int a) {...}
callFoo() {
foo(std::bind(&Baz::bar, this, _1);
}
}
However, in my app, I often need to invoke foo in places where I hold a pointer to an object that has a valid member function which could serve as an argument to foo. I don't really want to give every class that happens to hold a valid pointer a method that invokes 'foo'. In fact, I would prefer that those classes don't even know about foo.
I want a method that looks like this:
template<class T>
static void callFooSugar(T* ClassPointer, [What goes here?] ClassMethod);
So I could do this:
Baz MyBaz;
callFooSugar(&MyBaz, bar);
Is there a way to write callFooSugar without resorting to macros? I am compiling with C++11.
I'm having difficulties defining a function pointer that can point to any member function (not just member functions for the specified class).
For instance, C++ forces me to specify the class that a function pointer to a member function would point to:
typedef void (Foo::*MyFunctionPointerTypeName)(int);
but what if the class member function that this function pointer is going to point to isn't in Foo? How then would I write this, or what alternative approach could I use?
Update: For anyone looking for a quick answer on how to accomplish this with a C++11 std::function (as tutorials on the subject seem to assume alot of the reader):
Definition (from within Foo):
std::function<void(int)> _fun;
Binding (from any class):
objFoo->_fun = std::bind(&SomeOtherClass::memberFunction,
this, std::placeholders::_1);
Calling it (from within Foo)
if(_fun != nullptr) _fun(42);
If your function has no parameters, you can remove std::placeholders::_1. And if your function has two parameters you'll need to also add std::placeholders::_2 as a parameter to std::bind. Similarly for three parameters, four parameters, etc.
You cannot write a member pointer that could point to a member of any class. Remember: one of the arguments of a member pointer is the class instance itself. And pointers are typed, so the type of its arguments is very much a part of the pointer's type.
You can use std::function however, which can store all sorts of callables. How you would actually call it (ie: what parameters you give it) depends on your needs, as you haven't explained what you're trying to do.
Use inheritance:
#include <iostream>
struct Foo {};
struct Bar : public Foo
{
int F0()
{
return 0;
}
};
struct Baz : public Foo
{
int F1()
{
return 1;
}
};
int main(int argc, char **argv)
{
int (Bar::*pF0)() = &Bar::F0;
int (Baz::*pF1)() = &Baz::F1;
int (Foo::*pointer1)() = static_cast<int (Foo::*)()>(pF0);
int (Foo::*pointer2)() = static_cast<int (Foo::*)()>(pF1);
Bar r;
Baz z;
// Pointer to Foo member function calling Bar member function
std::cout << (r.*pointer1)() << '\n';
// Pointer to Foo member function calling Baz member function
std::cout << (z.*pointer2)() << '\n';
return 0;
}
Output:
0
1
Hope it helps.
Here are the requirements posed by my application. I have a class A, that accepts a function pointer say cFunc, Basically in my implementation of A, I have it call cFunc multiple times.
The cFunc pointer itself should point to different functions depending upon the application. Thus for each application I create a class with the same function definition as cFunc, however I cannot assign the class's member function to this pointer
class A {
typedef double (*Def_CFunc)(std::vector<double>);
A(Def_CFunc _cFunc) { // Some implementation}
// Other Functions
};
class B { double someFunc(std::vector<double> b); };
class C { double someOtherFunc(std::vector<double> a); };
int main () {
B firstObj;
C secondObj;
// Depending upon the situation, I want to select class B or C
double (*funcPointer)(std::vector<double>) = firstObj.someFunc; // Error in this line of code
A finalObj(funcPointer);
}
So how do I make it such that any class with a member function of the given format can be used to initialize the class A?
I'm not sure what exactly your requirements are, but it looks like you want an interface (or abstract base class in C++ lingo).
If both B and C inherit from a common base class, you can pass a pointer to this base class and invoke functions on it:
class I { virtual double func(std::vector<double> a) = 0; }
class B : public I { double func(std::vector<double> a); };
class C : public I { double func(std::vector<double> a); };
You can pass an I* pointer to A and just use i->func.
Pointer to member function has different syntax than pointer to ordinary function and can only point to a method of one given class. To be able to point to methods in different classes use boost::function or if C++11 is available use std::function. These can hold any method or function of a given signature.
What you need is std::function together with either std::bind or lambda expressions (or the Boost equivalent of the first two), because member function pointers don't allow you to do that.
You can do it using std::bind + std::function. Lets write some template class wrapper, that takes any static type as input. Then use this wrapper in free function switch_obj. Usage is very simple.
typedef std::function<double(std::vector<double>)> my_foo;
template<class C>
struct switcher
{
static my_foo convert(C* obj)
{
return my_foo( std::bind(&C::someFunc,obj,std::placeholders::_1) );
}
};
template<class T>
my_foo switch_obj(T* obj)
{
return switcher<T>::convert(obj);
}
void main()
{
B firstObj;
C secondObj;
auto f = switch_obj(&firstObj);
A a(f);
}
Here is the problem i am facing, does anyone have solution?
Class A: public class B
{
// I want to pass a reference of B to Function
}
void ClassC::Function(class& B)
{
//do stuff
}
The way you are declaring the class is wrong:
class A : public B // no more class keyword here
{
}; // note the semicolon
void ClassC::Function(const B &b) // this is how you declare a parameter of type B&
{
}
You simply need to pass the object of type A to the Function. It'll work.
It's good to declare the parameter as const if you want to take derived types too.
To pass the this instance, you'd simply call:
classCObject.Function(*this);
Are you just having trouble with the syntax? It should be
void ClassC::Function(B& b)
{
b.DoSomething();
}
to make b a reference of type B.