首页 > 解决方案 > 使用另一个函数作为类中的参数调用函数

问题描述

我试图构建代码来传递要在另一个函数中使用的函数。下面是我尝试过的代码,它在函数之外工作(所以如果我删除与类 Foo 相关的所有内容,它会工作),但我不知道如何让它在类本身内工作。如何在类中传递一个函数?我尝试了this->part1_math_class,Foo::part1_math_classpart1_math_class,没有一个工作。

// Example program
#include <iostream>
#include <string>
#include <stdint.h>
#include <functional>

int64_t loop(std::string partialMath, std::function<int64_t(std::string)> recurse)
{
    while (partialMath.find("(") != std::string::npos)
    {
        auto posClose = partialMath.find(")");
        auto posOpen = partialMath.rfind("(", posClose);

        std::string sub = partialMath.substr(posOpen + 1, posClose - posOpen - 1);

        int64_t resultInner = loop(sub, recurse);
        partialMath.replace(posOpen, sub.size() + 2, std::to_string(resultInner));
    }

    return recurse(partialMath);
}

int64_t part1_math(std::string math)
{
    return 0;
}

int64_t part2_math(std::string math)
{
    return 1;
}

class Foo {
public:
    Foo() { }
    
    int64_t loop_class(std::string partialMath, std::function<int64_t(std::string)> recurse)
    {
        while (partialMath.find("(") != std::string::npos)
        {
            auto posClose = partialMath.find(")");
            auto posOpen = partialMath.rfind("(", posClose);
    
            std::string sub = partialMath.substr(posOpen + 1, posClose - posOpen - 1);
    
            int64_t resultInner = loop_class(sub, recurse);
            partialMath.replace(posOpen, sub.size() + 2, std::to_string(resultInner));
        }
    
        return recurse(partialMath);
    }
    
    int64_t part1_math_class(std::string math)
    {
        return 2;
    }
    
    int64_t part2_math_class(std::string math)
    {
        return 3;
    }
    
    int64_t runLoop()
    {
        return loop_class("(1 + 2)", Foo::part1_math_class);
    }
};

int main()
{
  std::cout << loop("(1 + 2)", part1_math) << std::endl;  // this one works
  Foo bar;
  std::cout << bar.runLoop() << std::endl;  // this one does not even compile
  return 0;
}

标签: c++

解决方案


关于

    int64_t runLoop()
    {
        return loop_class("(1 + 2)", Foo::part1_math_class);
    }

Foo::part1_math_class()std::function<int64(std::string)>当使用正确的对象调用时,具有匹配的签名。在这种情况下,this将是指向预期对象的指针。因此,它必须以某种方式被“欺骗”到调用中。

一种简单的方法是使用仿函数而不是函数。仿函数是一个重载的类,operator()并且可以像函数一样工作,但具有额外的上下文。

std::function参数可以接受函子和函数。

恕我直言,编写仿函数的最简单方法是lambda

    int64_t runLoop()
    {
        return loop_class("(1 + 2)",
          [this](std::string math) { return part1_math_class(math); });
    }

this被捕获。签名匹配,因为参数是兼容的,并且返回类型是从 lambda 的主体中自动检测并匹配的。

coliru 现场演示


推荐阅读