【问题标题】:How to pass a private member function as an argument如何将私有成员函数作为参数传递
【发布时间】:2019-12-28 02:40:01
【问题描述】:

ROS中,有一个函数叫做NodeHanle::subscribe(Args...)NodeHandle::subscribe。这使您可以将 PRIVATE 成员函数作为回调传递。

但是,当我自己尝试时(使用 std::bind 传递私有成员函数),我的编译器总是失败并抱怨 Foo::foo() is a private member function。当我将Foo::foo 更改为公共功能时,一切正常。

template<typename T>
void getWrapper1(void(T::*fn)(int), T *t) { 
  return [&](int arg) {
    std::cout << "process before function with wrapper" << std::endl;
    (t->*fn)(arg);
    std::cout << "process after function with wrapper" << std::endl;
  };
}

void getWrapper2(std::function<void(int)> fn) {
  return [=](int arg) {
    std::cout << "process before function with wrapper" << std::endl;
    fn(arg);
    std::cout << "process after function with wrapper" << std::endl;
  }
}

class Foo {
private:
  void foo(int a) {
    std::cout << __FUNCTION__ << a << std::endl;
  }
}

int main(int argc, char** argv) {
  Foo foo_inst;
  auto func1 = getWrapper1(&Foo::foo, &foo_inst); // fail because foo is private
  auto func2 = getWrapper2(std::bind(&Foo::foo, &foo_inst, std::placeholders::_1));  // fail because foo is private
  func1(1);
  func2(2);
  return 0;
}

来自this answer,使用std::function也可以传递私有成员函数。但是我尝试过的不同。

值得一提的是,在getWrapper2 中我使用[=] 而不是[&amp;],因为使用[&amp;] 可能会导致段错误。为什么它必须是“价值捕获”?

平台:GCC 5.4.0、c++14、ubuntu16.04

【问题讨论】:

  • 您无法在main 中访问Foo::foo,如果它是私有的。这就是“私人”的含义。
  • @molbdnilo 那么如果我将它绑定到Foo 就可以了吗?
  • 是的。它的工作方式与对私有成员的任何其他访问一样。

标签: c++ functional-programming ros


【解决方案1】:

你必须从内部传递它。您不能从类外部访问私有函数。甚至没有指向私人东西的指针。私人是私人的。

class Foo {
    void foo(int a) {
        std::cout << __FUNCTION__ << a << std::endl;
    }

 public:
    auto getWrapper() {
        // using a lambda (recommended)
        return getWrapper2([this](int a) {
            return foo(a);
        });

        // using a bind (less recommended)
        return getWrapper2(std::bind(&Foo::foo, this, std::placeholders::_1));
    }
}

为什么它必须是“价值捕获”?

两个包装器都需要值捕获。您的 Wrapper1 有未定义的行为。

考虑一下:

// returns a reference to int
auto test(int a) -> int& {
    // we return the local variable 'a'
    return a;
    // a dies when returning
}

同样的事情发生在 lambda 上:

auto test(int a) {
    // we capture the local variable 'a'
    return [&a]{};
    // a dies when returning
}

auto l = test(1);
// l contain a captured reference to 'a', which is dead

指针按值传递。指针本身就是一个对象。指针有自己的生命周期并且可以死亡。

auto test(int* a) -> int*& {
    // we are still returning a reference to local variable 'a'.
    return a;
}

而且...你猜对了,std::function 也是如此:

auto test(std::function<void(int)> a) {
    // return a lambda capturing a reference to local variable 'a'.
    return [&a]{};
}

【讨论】:

  • 谢谢,这很有意义。您是否也知道为什么在 getWrapper2 中,它必须是“价值捕获”? getWrapper1 与“引用捕获”配合得很好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 2020-02-17
  • 1970-01-01
  • 2012-04-28
  • 2018-09-18
相关资源
最近更新 更多