【问题标题】:Passing non-static member function as parameter of function传递非静态成员函数作为函数的参数
【发布时间】:2017-11-22 09:16:45
【问题描述】:

我需要将非静态成员函数传递给参数

class Foo {
    void f() {}
    void caller() {
        //calling of g() happens here using f()
    }
};

Class Goo {
    std::map<int,std::vector<std::function<void()>>>> m;
    void g(int i, std::function<void()> const& h) {
        m[i].push_back(h);
    }
}

我试着打电话 g(f), g(Foo::f), g(std::make_fn(Foo::f), g(std::make_fn(Foo:f, this), g(this.f) 并且还尝试将其作为参考传递(尽管应该)。
我得到的错误是无效使用非静态成员函数。

编辑:我在g() 后面添加了功能

【问题讨论】:

  • 请注意,您不能将引用存储在容器中。如果您想要引用,请改用指针。在这种情况下,这是没有意义的。只存储值。

标签: c++ c++11


【解决方案1】:

你必须解决的问题是 this 参数对于非静态成员函数是隐式的。这意味着如果你想稍后调用成员函数,你也需要将指针传递给对象。

其中一种方法是使用std::bind(&amp;Foo::f, this)

更新 1 您可以使用smart pointersFoo 的生命周期与std::bind 创建的仿函数的生命周期联系起来。

class Foo : std::enable_shared_from_this<Foo> {
    void f() {}
    void caller() {
        // CAVEAT! shared_from_this() will work iff instance of `Foo` is already owned 
        // by an std::shared_ptr. This means that when you create `Foo`
        // you must do so via std::make_shared<Foo>()
        g(std::bind(&Foo::f, shared_from_this()));
    }
};

这就是如何将 Foo 的生命周期绑定到通过 std::bind 生成的 std::function 的生命周期。

请参阅代码注释中的警告。

更新 2 你的函子向量不正确。

std::map<int,std::vector<std::function<void()>const&>> m;

必须

std::map<int,std::vector<std::function<void()>>> m;

(没有 const 引用)

【讨论】:

  • 这个解决方案给了我一组全新的错误。 g() 实际上获取函数并将它们推送到一个向量中,并在其中存储它们以便稍后执行。它给了我关于形成引用类型和分配器错误的错误
  • @ZergOvermind 你想达到什么目的?
  • 这些函数应该在给定事件发生时执行。 g() 代表订阅函数,f() 应该是一个函数,对于给定的对象,它会使用它将收到的任何数据执行某些操作,或者它会简单地记录事件发生的事实。更具体地说,我存储函数向量的映射,其中每个事件都有核心的函数向量,然后执行。
  • 我添加到g()
  • @ZergOvermind 有一个解决方案涉及绑定智能指针(准确地说是std::shared_ptr)而不是this。这将确保Foo 的实例处于活动状态,以便函数可以正确执行。但此解决方案要求 Foo 已经在 std::shared_ptr 所有权下,这可能会或可能不会感到笨拙,具体取决于您架构的其余部分。
【解决方案2】:

您可以使用类型安全的Functor 模式将函数作为参数传递,而不是干巴巴地传递函数地址并希望得到正确的转换。

即为函数 f() 声明一个类,并将实现放在 operator() 中。您可以使用构造函数来预加载任何类型的函数参数,或者使用重载的 operator() 的参数。你可以像对象一样传递函数,缓存值只要你喜欢,当你不再需要它时,可以释放任何内存。

【讨论】:

    【解决方案3】:

    你可以使用lamba来封装一个成员函数调用:

    void g(std::function<void()> const&);
    
    class Foo
    {
        void f(void) {}
    
        void caller(void)
        {
            g
            (
                 ::std::function<void (void)>
                 {
                      // we need to capture "this" because f is a non-static member function
                      [this](void) -> void
                      {
                          f();
                      }
                  }
             );
        }
    };
    

    【讨论】:

      【解决方案4】:

      您可以使用 std::bind 与 this 绑定函数

      g(std::bind(&Foo::f, this));

      这里是完整的解决方案:

      #include <functional>
      #include <iostream>
      void g(std::function<void()> const& func){
              func();
      };
      class Foo {
      public:
          void f() const{std::cout<<"function f()\n";}
          void caller() const {
              //calling of g() happens here using f()
              g( std::bind(&Foo::f, this) );
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-18
        • 2019-03-14
        • 1970-01-01
        • 2011-05-31
        • 2013-06-29
        • 2020-12-31
        • 1970-01-01
        • 2011-01-07
        相关资源
        最近更新 更多