7

我有这个 C++ 类,它compute是我想用“计算内核”提供的一个大而复杂的方法,它是同一个类的方法。我想我会做一些类似的事情

class test {
int classVar_ = 42;

int compute_add(int a, int b)
{
   compute(int a, int b, this->add_())
}

int compute_mult(int a, int b)
{
   compute(int a, int b, this->mult_())
}


int compute_(int a, int b, "pass in add or multiply as f()")
{
   int c=0;
   // Some complex loops {
   c += f(a,b)
   // }
   return c;
}

int add_(int a, int b){a+b+classVar_;}
int multiply_(int a, int b){a*b+classVar_;}
...

}

但我不确定我将如何通过addmultiply. 这种方法的一种替代方法是传入ENUM某种类型的 an 来指定add()or multiply(),但我想避免在循环中使用switchor 。if

这里的最佳做法是什么?

4

3 回答 3

5

正如您所怀疑的,传递成员函数指针是可以接受的做法。

如果你需要知道语法,它是:

int compute_(int a, int b, int (test::*f)(int,int))
{
   int c=0;
   // Some complex loops {
   c += (this->*f)(a,b)
   // }
   return c;
}

使用整数表示成员函数和切换会引入程序员开销,以便在可用操作列表更改时保持最新状态。所以你不希望这样,除非在特定情况下有一些重要的原因。

一种替代方法是compute更通用——而不是采用成员函数,而是编写一个采用任何可调用类型的函数模板:

template <typename BinaryFunction>
int compute_(int a, int b, BinaryFunction f) {
    // body as before but `f(a,b)` instead of `(this->*f)(a,b)`
}

如果有人想将它与他们自己发明的某个运算符一起使用,这个更通用的模板非常棒,这不是test. 但是,在成员函数的情况下使用起来更加困难,因为有人需要捕获this. 有几种方法可以做到这一点 - C++11 lambda boost::bind, 或写出一个仿函数。例如:

template <typename BinaryFunction>
int compute_(int a, int b, BinaryFunction f) {
    // body as before with `f(a,b)`
}

int compute_(int a, int b, int (test::*f)(int,int))
{
    return compute_(a, b, bind_this(f, this));
}

定义bind_this有点麻烦:就像std::bind1st我们想使用 3-arg 仿函数而bind1st只使用二元仿函数一样。boost::bind,并且std::bind在 C++11 中,更加灵活,并且会处理额外的参数。以下将适用于这种情况,但通常不适用于绑定 2-arg 成员函数:

struct bind_this {
    int (test::*f)(int,int);
    test *t;
    int operator(int a, int b) const {
        return (t->*f)(a,b);
    }
    bind_this(int (test::*f)(int,int), test *t) : f(f), t(t) {}
};

在 C++11 中,您可以只使用 lambda:

int compute_(int a, int b, int (test::*f)(int,int))
{
    return compute_(a, b, [=](int c, int d){ return (this->*f)(c,d) });
}
于 2012-06-29T10:45:45.100 回答
1

你有两种选择:

  1. 使用指向成员函数的指针
  2. 使用lambda 函数

使用指向成员函数的指针的示例:

#include <iostream>

class D
{
public:
  D(int v ) : classVar_(v){}
  int add_(int a, int b){return (a+b+classVar_);}
  int multiply_(int a, int b){return (a*b+classVar_);}
private:
  int classVar_;
};

class test {
public:

int compute_(int a, int b, D &d, int (D::*f)(int a, int b))
{
   int c=0;
   // Some complex loops {
   c += (d.*f)(a,b);
   // }
   return c;
}

};

int main()
{
  test test;
  D d(1);

  std::cout<<"add : " << test.compute_( 5, 4, d, &D::add_ ) << std::endl;
  std::cout<<"add : " << test.compute_( 5, 4, d, &D::multiply_ ) << std::endl;
}

使用 lambda 的示例:

#include <iostream>
#include <functional>

class D
{
public:
  D(int v ) : classVar_(v){}
  int add_(int a, int b){return (a+b+classVar_);}
  int multiply_(int a, int b){return (a*b+classVar_);}
private:
  int classVar_;
};

class test {
public:

int compute_(int a, int b, std::function< int(int,int) > f)
{
   int c=0;
   // Some complex loops {
   c += f(a,b);
   // }
   return c;
}

};

int main()
{
  test test;
  D d(1);

  std::cout<<"add : " << test.compute_( 5, 4, [&d](int a, int b){ return d.add_(a,b); } ) << std::endl;
  std::cout<<"add : " << test.compute_( 5, 4, [&d](int a, int b){ return d.multiply_(a,b); } ) << std::endl;
}
于 2012-06-29T10:42:53.883 回答
1

使用指向函数的指针。

int compute(int a, int b, int (test::*f) (int, int) )
{
   int c=0;
   // Some complex loops {
   c += (this->*f)(a,b)
   // }
   return c;
}
于 2012-06-29T10:47:07.373 回答