如何最好地将方法传递到同一类的方法中

Nic*_*mer 7 c++ member-function-pointers

我有这个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_;}
...

}
Run Code Online (Sandbox Code Playgroud)

但我不确定我会怎样传递add或传递multiply.这种方法的另一种方法是传递ENUM某种类型来指定add()multiply(),但我想避免循环中的一个switchif内部.

这里最好的做法是什么?

Ste*_*sop 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;
}
Run Code Online (Sandbox Code Playgroud)

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

一种替代方法是使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)`
}
Run Code Online (Sandbox Code Playgroud)

如果有人想将它与自己发明的某个运算符一起使用,那么这个更通用的模板是很好的,这不是其成员函数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));
}
Run Code Online (Sandbox Code Playgroud)

定义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) {}
};
Run Code Online (Sandbox Code Playgroud)

在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) });
}
Run Code Online (Sandbox Code Playgroud)

  • @Nico:我把它称为`compute_(1,2,&test :: add_)`,但我已经准备好相信Mat的建议在类`test`的范围内是正确的.显然,当形成指向成员函数的指针时,`this - > _ add`*与*_add`不相同,即使在调用该成员函数时它是相同的. (2认同)