我想做以下事情:
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));
};
B类应该解决函数func指定的数学问题。 A类现在应该使用B来解决func = f的这个问题。成员函数f访问A的私有数据成员。 问题是,当然我不能简单地将指针传递给成员函数。我知道有办法做到这一点,但B应该仍然能够承担任何功能,而不仅仅是A的成员。 到现在为止,我刚刚制作了f和A静态的成员,但我认为这是一个相当糟糕的设计。你能想到解决这个问题吗?
答案 0 :(得分:3)
如何使用多态作为当前设计的替代方案?
例如:
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);
答案 1 :(得分:3)
您可以使用标准std::function<>
模板作为函数的多态包装。
您的班级B
只是存储std::function<double (double)>
的实例并通过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;
};
当您的班级A
使用其成员函数(B
)构建其f
成员时,感谢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)) { }
};
我们现在可以简单地使用它:
int main() {
A a(42);
a.b.foo(2); // Output : 84
}
<强> Live demo here 强>
答案 2 :(得分:2)
这是一个完整的样本程序。
#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;
}
请注意,你不要在那里销毁b
,同时请记住你将this
传递给B
,这可能是危险的(B
可能还活着在A
被销毁后,如果您在this
内使用f
...繁荣!)。
我还建议避免使用指针,如果使用std::unique_ptr
编辑:没有b
作为指针的版本std::function
和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;
}
答案 3 :(得分:0)
由于函数f()不是静态的,它的类型是&#34; double(A :: *)(double)&#34 ;, not&#34; double(*)(double)& #34;
然而,对于这种特殊情况,最好重新设计。
真的A是由问题解决者(B类)的数据和实例组成,还是A由数据组成并将某些操作委托给B?
B类真的需要一些人来了解A类中的方法,还是需要某种格式的数据?
class DataType {};
class ResultType {};
class A
{
DataType data;
DataType preprocess(Data d) {/*...*/}
ResultType process() { return B::compute(data); }
bool isSolvable() { return B::solve(preprocess(data)); }
};
class B
{
public:
ResultType compute(DataType);
bool solve(DataType);
};
答案 4 :(得分:0)
可能的解决方案:
class A
{
B* b;
static double f(double d); //static change function type form `double(A::*)(double)` to `double(*)(double)`
public:
A()
{
b = new B(f);
}
}
唯一的缺点是f
无法从A
或B
获取任何数据。