I want to do the following:
class A{
private:
//some data
B b;
double f(double);
public:
A(){
b = new B(f); // does not work of course
}
};
class B{
public:
B(double (*func)(double));
};
Class B is supposed to solve a mathematical problem specified by the function func. Class A should now use B to solve this problem for func=f. The member function f accesses the private data members of A. The problem is, of course that I cannot simply pass a pointer to member function. I know there are ways to do that, but B should still be able to take any function, not only members of A. Until now, I just made f and the members of A static, but I think this is a rather bad design. Can you think of any workaround for this?
You can use the standard std::function<>
template as a polymorphic wrapper for your functions.
Your class B
simply store an instance of std::function<double (double)>
and call it through foo
:
class B
{
public:
B(const std::function<double (double)>& func) : func(func) {}
void foo(double d)
{
std::cout << func(d);
}
private:
std::function<double (double)> func;
};
While your class A
build its B
member with one of its member function (f
), thanks to std::bind
:
class A
{
public:
double md;
B b;
double f(double d) const
{
return md * d;
}
public:
A(double d) : md(d), b(std::bind(&A::f, this, std::placeholders::_1)) { }
};
We can now simply use it :
int main() {
A a(42);
a.b.foo(2); // Output : 84
}
Live demo here.
How about using polymorphism as an alternative to your current design?
For example:
class A
{
protected:
virtual double f(double x) = 0;
};
class B1 : public A
{
public:
double f(double x) {return x+1.0;}
};
class B2 : public A
{
public:
double f(double x) {return x+2.0;}
};
...
A* arr[4];
arr[0] = new B1;
arr[1] = new B2;
arr[2] = new B1;
arr[3] = new B2;
for (int i=0; i<4; i++)
cout << arr[i]->f(0.0);
This a fully working program for your sample.
#include <memory>
#include <iostream>
#include <functional>
class B
{
public:
B(std::function<double(double)> func)
{
std::cout<<func(1.0);
}
};
class A
{
private:
std::unique_ptr<B> b;
double f(double)
{
std::cout<<"A::f";
return 2.0;
}
public:
A() : b(new B(std::bind(&A::f, this, std::placeholders::_1)))
{
}
};
int main()
{
A a;
}
Please note you don't destroy b
there and also keep in mind you are passing this
to B
, thing that might be dangerous (B
might be alive after A
is destroyed and if you use this
inside f
... boom!).
I would also suggest avoiding pointers and if this is not possible using std::unique_ptr
EDIT: And a version without b
as pointer, std::function
and std::bind
#include <iostream>
class A;
class B
{
public:
B(A* obj, double(A::*func)(double))
{
std::cout<<(obj->*func)(1.0);
}
};
class A
{
private:
B b;
double f(double)
{
std::cout<<"A::f";
return 2.0;
}
public:
A():b(this, &A::f)
{
}
};
int main()
{
A a;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With