问题
I have a problem in C++ that is similar to this example problem. In this case I have two member-functions that have an identical interface. Based on the information in a string passed to the super function, I would like to assign one of the two member functions to the variable class_func
. Is there a way to do this?
// 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;
}
In other words, I am trying to assign the member-function add
or subtract
to the name class_func
, so the code underneath the if
statement in master_function
can be uniform regardless of which function the user wants to use. In the form shown below I get the error Reference to non-static member function must be called out
, but I am not totally sure what this means or how to fix it. In addition, I am using a C++17 compiler, so if there is a modern approach that works best with C++17 I would be interested in learning it.
回答1:
The term you are looking for is member function pointer, but we can do without explicitly specifying that type. The problem with your code is not only in the way you try to refer to a member function (that would be &TestClass::add
), but also that you create those aliases in a nested scope (under if
/else
), meaning they won't be visible in the return
statement.
The simplest change is this:
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);
This works because the add
and subtract
functions have the exact same type:
double (TestClass::*)(double a, double b)
But yeah, why are those functions not static
? They do not work with a class' instance. Make them static
and the above will still work, just note that the type of class_fun
will be a simple function pointer:
double (*)(double a, double b)
Now that you know the types, you could change this in a way that does not privilege one function before the other in the code:
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);
As mentioned in the comments, as that if
-else
chain starts to get longer, it makes more and more sense to use a (hash)map between strings and function pointers.
来源:https://stackoverflow.com/questions/56212392/how-do-i-re-assign-a-function-name-in-c