Как переназначить имя функции в C ++ - PullRequest
3 голосов
/ 20 мая 2019

У меня проблема в 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;
}

Другими словами, я пытаюсь присвоить функции-члену add или subtract имя class_func, поэтому код под *Оператор 1008 * в master_function может быть одинаковым независимо от того, какую функцию хочет использовать пользователь.В приведенной ниже форме я получаю сообщение об ошибке Reference to non-static member function must be called out, но я не совсем уверен, что это значит или как ее исправить.Кроме того, я использую компилятор C ++ 17, поэтому, если есть современный подход, который лучше всего работает с C ++ 17, мне было бы интересно изучить его.

1 Ответ

6 голосов
/ 20 мая 2019

Вы ищете термин указатель на функцию-член , но мы можем обойтись без явного указания этого типа.Проблема с вашим кодом заключается не только в том, как вы пытаетесь обратиться к функции-члену (это будет &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);

Это работает, потому что функции add и subtract имеют точноетот же тип:

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);

Как упоминалось в комментариях, поскольку цепочка if - else начинает становиться длиннее, она делает большеи больше смысла использовать (хеш) карту между строками и указателями на функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...