我的一般目的是设计一个优化器。它是一个搜索给定函数的最大值的类。我打算在代码的其他部分使用这个优化器,包括另一个类的方法。
我已经实现了这样的优化器:
class MyOptimizer {
public:
typedef double (*FuncType)(double);
MyOptimizer(FuncType f, double a, double b) : _f(f), _a(a), _b(b) {}
double optimize() const {
// do something with _f in order to find the maximum
return maximum;
}
private:
double _a;
double _b;
FuncType _f;
}
我想在我的代码的其他部分中使用优化器作为库。例如:
class AnyClass {
public:
...
double func(double x) const {
// using members of the instance
}
void aMethod() {
MyOptimizer opt(func, 0.0, 1.0);
double bestArgument = opt.optimize();
}
...
};
但我不允许这样做,因为AnyClass::func
的类型签名不同。
设计优化器以便在其他代码中使用方便的最佳方法是什么?一个代码示例将不胜感激。
我需要一个C ++ 1998/2003标准的解决方案。
答案 0 :(得分:4)
问题是AnyClass::func
实际上需要两个参数,正式x
但它还需要this
。如果你能买得起C ++ 11,那么std::function
就是你的朋友(或Callable
模板):
MyOptimizer::MyOptimizer(std::function<double(double)> f, double a, double b);
然后,您可以将对象方法包装在lambda function:
中MyOptimizer opt([this] (double x) -> double { return func(x); }, 0.0, 1.0);
如果没有,您需要编写自己的包装类来存储this
的值并公开operator()
并传递此类对象而不是函数指针。
template<class AnyClass>
class AnyClassWrapper {
AnyClass *that;
typedef double (AnyClass::*FuncType)(double);
FuncType func;
public:
AnyClassWrapper(AnyClass* _that, FuncType _func): that(_that), func(_func) { }
double operator()(double x) {
return that->*func(x);
}
};
此类的实例现在可以像函数一样使用:double y = instance(x)
。您需要对构造函数进行模板化(编辑:以及整个类,同时您还要存储函数),以便能够接受普通函数指针以及广义函数像这样的对象,使用两种语法相同的事实:
template<class Func>
MyOptimizer::MyOptimizer(Func& f, double a, double b);
然后你可以将它用于非静态函数:
// within AnyClass
AnyClassWrapper<AnyClass> callable(this, &AnyClass::f);
MyOptimizer opt(callable, 0.0, 1.0);
但是同一个班级也接受正常的功能:
// anywhere
MyOptimizer opt2(std::sin, 0.0, 1.0);
请注意,上面的内容基本上是实现了lambda函数在幕后所做的事情。如果需要,您可以类似地向后移动std::function
- 这将允许优化器不需要任何模板。
答案 1 :(得分:1)
最简单的解决方案是让 AnyClass 继承优化器。喜欢:this。 但是如果你的死设置在backCalling上,你应该知道你的C ++声明有错误。我会评论你的问题,而不是发布答案,但StackOv。要求至少50rep评论!
答案 2 :(得分:1)
您可以使用指针到成员的功能。对此的一个很好的描述是here。
这是一个实现。
template <class T>
class MyOptimizer {
public:
typedef double (T::*FuncType)(double) const;
MyOptimizer(T* instance, FuncType f, double a, double b) : _instance(instance),_f(f), _a(a), _b(b) {}
double optimize() const {
// do something with _f in order to find the maximum
return 1.0;
}
private:
double _a;
double _b;
FuncType _f;
T* _instance;
};
class AnyClass {
public:
double func(double x) const {
// using members of the instance
return 0.0;
}
void aMethod() {
MyOptimizer<AnyClass> opt(this, &AnyClass::func, 0.0, 1.0);
double bestArgument = opt.optimize();
}
};
答案 3 :(得分:0)
如果您可以选择更改Print
,请将其更改为类模板或使用MyOptimizer
而不是函数指针as suggested by @TheVee
如果您无法更改std::function
,我会提出一些建议。
要将MyMonitor
与AnyClass::func
一起使用,您需要一个非成员函数或MyOptimizer::optimize
成员函数。如果这些功能能够访问您要呼叫static
的{{1}}对象,则这些功能都可以正常工作。
使用非会员功能
AnyClass
然后
func
使用// Global variable
AnyClass* currentAnyClass = nullptr;
// Non-member function
double funcWrapper(double x)
{
assert(currentAnyClass != nullptr);
return currentAnyClass->fun(x);
}
会员功能
它遵循几乎相同的策略。我比第一次更喜欢这个,因为它将void aMethod() {
currentAnyClass = this;
MyOptimizer opt(funcWrapper, 0.0, 1.0);
double bestArgument = opt.optimize();
currentAnyClass = nullptr;
}
和static
保持在`AnyClass的范围内。
currentAnyClass