传递成员函数(或变通方法)

时间:2014-07-23 12:46:01

标签: c++

我想做以下事情:

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静态的成员,但我认为这是一个相当糟糕的设计。你能想到解决这个问题吗?

5 个答案:

答案 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::functionstd::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无法从AB获取任何数据。