【问题标题】:How do I re-assign a function name in C++如何在 C++ 中重新分配函数名
【发布时间】:2019-05-20 06:38:56
【问题描述】:

我在 C++ 中有一个与此示例问题类似的问题。在这种情况下,我有两个具有相同接口的成员函数。根据传递给超级函数的字符串中的信息,我想将两个成员函数之一分配给变量class_func。有没有办法做到这一点?

// test.hpp
class TestClass
{
public:
    double master_function(double a, double b, std::string func_name);
private:
    double add(double a, double b);
    double subtract(double a, double b);
};

// test.cpp
double TestClass::master_function(double a, double b, std::string func_name)
{
    if (func_name == std::string("Add") const auto& class_func = add;
    else const auto& class_func = subtract;
    return class_func(a, b);
}
// =========================================================================

double TestClass::add(double a, double b)
{
    return a + b;
}
// =========================================================================

double TestClass::subtract(double a, double b)
{
    return a - b;
}

换句话说,我试图将成员函数addsubtract 分配给名称class_func,因此master_functionif 语句下面的代码可以是统一的,无论哪个函数用户想要使用。在下面显示的表格中,我收到错误Reference to non-static member function must be called out,但我不完全确定这意味着什么或如何解决它。此外,我使用的是 C++17 编译器,所以如果有一种最适合 C++17 的现代方法,我会有兴趣学习它。

【问题讨论】:

  • 如果func_name 是运行时字符串,那么除了使用一些哈希图之外别无选择,例如std::unordered_map.
  • 你能用std::function吗?而不是传递 std::string 您的函数将采用 std::function 并且用户会指定调用什么?我认为addsubtract 不能成为private,这可能会破坏目的。
  • 您应该阅读一下有关范围如何工作的信息,并且可能总是使用大括号。两者都会向您表明,您希望做的事情不可能按照您编写的方式进行。您当然可以拥有分配的函数指针或名称映射 -> 函数,但不清楚为什么需要它。你写的例子很简单,没有不必要的间接性。
  • 无关:你真的需要一个变量吗? return func_name == std::string("Add") ? add(a, b) : subtract(a, b);
  • @Retired Ninja:你说得对,这个简单的问题可以用更简单的方式解决;但是,这不是我正在研究的真正问题,而是一个更简单的示例,突出了我正在尝试解决的同一问题。

标签: c++ c++17


【解决方案1】:

您要查找的术语是成员函数指针,但我们可以不明确指定该类型。您的代码的问题不仅在于您尝试引用成员函数(即&TestClass::add)的方式,还在于您在嵌套范围内创建这些别名(在if/else下),这意味着它们不会在 return 语句中可见。

最简单的改变是这样的:

auto class_func = &TestClass::add; // pick one default

if (func_name == "Subtract")
{
    class_func = &TestClass::subtract;
}
else
{
    assert(func_name == "Add"); // optional
}

return class_func(a, b);

这是因为addsubtract 函数具有完全相同的类型:

double (TestClass::*)(double a, double b)

但是,是的,为什么这些功能不是static?它们不适用于类的实例。将它们设为static,上面仍然可以工作,只需注意class_fun 的类型将是一个简单的函数指针:

double (*)(double a, double b)

既然您知道了类型,您可以在代码中以一种不在另一个函数之前特权的方式进行更改:

decltype(&TestClass::add) class_func = nullptr;

if (func_name == "Add")
{
    class_func = &TestClass::add;
}
else if (func_name == "Subtract")
{
    class_func = &TestClass::subtract;
}

assert(class_func != nullptr);
return class_func(a, b);

正如 cmets 中所述,随着 if-else 链开始变长,在字符串和函数指针之间使用(散列)映射变得越来越有意义。

【讨论】:

  • 您也可以将其设为模板template <typename F> double master_function(double a, double b, F &&f) { return f(a, b); },然后使用master_function(1.1, 2.2, std::plus<void>{}) 调用它。
  • 是的,这就是我们在 C++ 中进行泛型编程的方式,所以我希望 @Jon 真的想要运行时选择行为(基于运行时值,而不是编译时类型)。
  • @LogicStuff 你是对的,我正在寻找运行时行为
猜你喜欢
  • 2016-06-27
  • 2015-09-23
  • 2018-05-26
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 2021-07-15
  • 2023-03-21
相关资源
最近更新 更多