【问题标题】:c++ pass data source function as parameterc ++将数据源函数作为参数传递
【发布时间】:2016-10-13 13:44:31
【问题描述】:

我有一个静态函数:

void E::createEP(std::list<double>* ret, double length, double (*getHeight)(double)) {
  // magic
  double sampleIntervall = //from magic

  double dist = 0;
  while (length - dist > -0.1) {
    ret->push_back(dist, (*getHeight)(dist));
    dist += sampleIntervall;
  }
}

在不同的调用中,我有两个不同的函数作为 getHeight() 传递:

  • 数据库包装类中的非静态函数
  • EcreateEP() 类型相同的 Object 中的函数(用于使用不同参数“重新创建”),它需要访问 Elements 字段,因此也不能是静态的。

是否可以将非静态函数作为参数传递给静态函数?

如果不是,最优雅的选择是什么?我不想在createEP() 中复制整个代码。

【问题讨论】:

    标签: c++ function c++11 static non-static


    【解决方案1】:

    您可以使用std::function。它将包装一个可调用类型,即具有重载函数运算符的函数、成员函数、对象。您只需要提供要使用的签名。所以在你的情况下你会有

    void E::createEP(std::list<double>* ret, double length, std::function<double(double)> getHeight) 
    

    然后要将成员函数与您要调用它的对象绑定,您可以使用lambda like

    [&](double val){ return object.FunctionName(val); }
    

    std::bind点赞

    std::bind(&ClassName::FunctionName, &object)
    

    【讨论】:

    • 您可以将 () 放在 lambda 上。我会在std::bind 自己之前放置更短(可能更高效)的 lambda。 (std::bind 实际上需要创建一个带有两个指针的数据结构,并实际调用成员函数指针,因为std::function 暴露了对底层类型的访问)。
    • @Yakk 最好先创建 lambda。
    • 我会在 lambda 表达式中输入什么作为参数?
    • 抱歉,我似乎无法编辑我的评论:我会放什么:[&]{ return this->getElevation(//here?);}
    • @Niklas 如果它是静态值,只需对其进行硬编码。如果您想要更改它的选项,那么您可以使用[&amp;](double val){ return object.function(val); }。我更新了答案,因为我忘记了你需要向它传递一个值。
    【解决方案2】:

    对于 c++11,最好的选择可能是使用 std::function&lt;double(double)&gt; 而不是原始函数指针。

    【讨论】:

      【解决方案3】:

      std::function在这里真的很有用

      看到这个:

      #include <functional>
      
      using funType = std::function<void(double)>;
      struct foo
      {
        void bar(double d) {};
        static void call(funType f) {};
      };
      
      void foo2(double)
      {
      }
      
      //...       
      foo f;
      //create lambda which calls member function
      auto f1 = [&f](double d) { f.bar(4); };
      
      foo::call(f1); //indirect call to member function due to lambda
      foo::call(&foo2); //call to non-member function.
      //...
      

      std::function 可以保存函数指针或 lambda,这与 c 风格的函数指针相比​​非常好。

      您也可以直接使用成员函数调用它,但这需要bind。 我认为将调用包装在 lambda 中的解决方案看起来更好一些。

      【讨论】:

        【解决方案4】:

        作为std::function的替代品

        void E::createEP(std::list<double>* ret,
                         double length,
                         const std::function<double (double)>& getHeight)
        

        你可以直接使用模板

        template <typename F>
        void E::createEP(std::list<double>* ret,
                         double length,
                         F&& getHeight)
        

        在这两种情况下都有正文

        {
          // magic
          double sampleIntervall = //from magic
        
            double dist = 0;
            while (length - dist > -0.1) {
                ret->push_back(dist, getHeight(dist));
                dist += sampleIntervall;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2016-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-12
          • 1970-01-01
          • 1970-01-01
          • 2015-06-09
          • 1970-01-01
          相关资源
          最近更新 更多