如何使用较少的参数从方法创建新函数?

时间:2013-06-17 13:42:32

标签: c++

我有两个类,ClassA和ClassB。 ClassA有三种方法:

double Foo(double, ClassB);
double Bar(double (*f)(double));
double Baz(double, ClassB);

我想在Foo中定义一个函数Qux,基于Baz,但没有ClassB类型的参数:即类型为“double Qux(double)”,以便我可以将它传递给Bar:

double ClassA::Foo(double x, ClassB y)
{
    // double Qux(double .) = Baz(., y)
    Bar((*Qux))
}

有人有任何想法吗?

我想有些人会回答这不是做这件事的好方法。因此,为了解释具体情况,我使用数值方法(http://en.wikipedia.org/wiki/Simpson%27s_rule)定价金融资产以计算积分:

ClassA: FinancialAsset

ClassB: PrincingModel

Foo: FinancialAsset.Price(date, PrincingModel)

Bar: FinancialAsset.SimpsonMethod(FunctionOneArgument)

Baz: FinancialAsset.FunctionTwoArguments(date, PrincingModel)

我正在寻找:

Qux: FunctionOneArgument(date) = FinancialAsset.FunctionTwoArguments(date, PrincingModel)

我不确定解决这种结构的好方法是什么。我有更好的/更多的c ++方法,我会采取:)

谢谢,

卡米尔

3 个答案:

答案 0 :(得分:2)

你不能完全这样做,因为你的Bar函数正在使用指向常规函数的指针,但你可以改用它:

class A {
    ...
  public:
    double Foo(double, ClassB);
    double Bar(std::function<double(double)> f);
    double Baz(double, ClassB);
};


double ClassA::Foo(double x, ClassB y)
{
    auto Qux = [&](double x) { Baz(x,y); };
    return Bar(Qux);
}

std::function是表示类似函数的对象的更通用的方法。您可以将常规函数,lambda或函数对象转换为它。

答案 1 :(得分:1)

根据您是否拥有C ++ 11,对于较旧的C ++版本,您需要std::bindstd::functionboost::bindboost::function

绑定允许您获取一个函数并绑定0个或多个参数,或重新排列参数。事实上,你上面的东西看起来像这样:

double ClassA::Foo(double x, ClassB y)
{
    boost::function<double> baz = boost::bind(this, ClassA::Baz, _1, y);
    Bar(baz);
}

Bar的签名将采用boost::function而不是函数指针。

请注意,我的语法可能稍微偏离绑定memeber函数,请查看文档以获取详细信息。

见这里: http://www.boost.org/doc/libs/1_53_0/libs/bind/bind.html

或者在这里:http://en.cppreference.com/w/cpp/utility/functional/bind

答案 2 :(得分:0)

您可以在不更改任何功能签名(以及C ++ 11或boost)的情况下执行此操作,但如果您可以避免,我不建议您这样做。它很难看,不是线程安全的,而且一般不太好:

#include <iostream>

struct B
{
    // some data in B
    int i;
};

struct A
{
    //some data in A
    double d;

    // the functions you defined in A    
    double Foo(double x, B y);
    double Bar(double (*f)(double));
    double Baz(double x, B y);
};

// a poor substitutes for closures
struct
{
    A *a;
    B *b;
} hack;

double Qux(double x2)
{
    // use the stored pointer to call Baz on x2
    return hack.a->Baz(x2, *hack.b);
}

double A::Foo(double x, B y)
{
    // store pointers for use in Qux
    hack.a = this;
    hack.b = &y;

    // do something with x
    d += x;

    double result = Bar(&Qux);

    return result;
}

double A::Bar(double (*f)(double))
{
    // do something with d, call the passed function
    d += 1;
    return f(d);
}

double A::Baz(double x, B y)
{
    // do something with the passed data
    return x + y.i;
}

int main()
{
    A a;
    a.d = 1.25;

    B b;
    b.i = 2;

    std::cout << a.Foo(.25, b) << std::endl; // should be 4.5    

    return 0;
}