首先,我建议在函数指针上使用std::function。它们更通用,可以用函数指针、函数对象或 lambda 表达式填充。典型用法如下所示:
#include <iostream>
#include <functional>
struct Funktor { // This is a callable class/object
void operator()() {
std::cout << "Funktor called." << std::endl;
}
};
void function() { // Normal function
std::cout << "Function called." << std::endl;
};
int main()
{
std::function<void()> lambdaFunction = [](){ std::cout << "lambda function executed." << std::endl;}; // And a lambda expression (fancy way to write a function where you need it)
std::function<void()> functionPointer = &function;
std::function<void()> callableObject = Funktor();
//This is the way you call functions with a std::function object, just like with a normal function
lambdaFunction();
functionPointer();
callableObject();
return 0;
}
但这并不能解决您在std::vector 中存储具有不同参数的函数的问题。由于它们具有不同的签名,因此您必须将它们视为不同的类型。喜欢int 和std::string。
为了存储不同类型的元素,STL 提供了std::tuple。您可以使用它来实现您的目标。
#include <iostream>
#include <functional>
#include <tuple>
int main()
{
// std::tuple takes multiple template arguments. Each corresponds to one element in the tuple
std::tuple<
std::function<void()>,
std::function<void(int)>
> functionTuple;
// To access a element of the tuple we call std::get<i> on the tuple
// This will return a reference to the element in the tuple and we
// can overwrite it with whatever we want
std::get<0>(functionTuple) = [](){
std::cout << "Function without arguments." << std::endl;
};
std::get<1>(functionTuple) = [](int arg){
std::cout << "Function without int as argument. Arg = " << arg << std::endl;
};
// We use std::get to get the function and the call it.
// The the trailing '()' and '(5)' are the actual function calls,
// just like in the example above
std::get<0>(functionTuple)();
std::get<1>(functionTuple)(5);
// You can also use std::get<...> with a type as argument.
// Have a look in the docs. Its a very nice feature of tuples
return 0;
}
如果你想同时实现,不同的参数和多个功能,你可以结合std::tuple和std::vector:
#include <iostream>
#include <functional>
#include <tuple>
#include <vector>
int main()
{
std::tuple<
std::vector<std::function<void()>>,
std::vector<std::function<void(int)>>
> functionTuple;
// We use push_back in this example, since we deal with vectors.
std::get<0>(functionTuple).push_back([](){
std::cout << "Function without arguments." << std::endl;
});
std::get<1>(functionTuple).push_back([](int arg){
std::cout << "Function without int as argument. Arg = " << arg << std::endl;
});
std::get<1>(functionTuple).push_back([](int arg){
std::cout << "Another function without int as argument. Arg = " << arg << std::endl;
});
std::get<0>(functionTuple).front()();
int i = 5;
// And we use foreach, to loop over all functions which take one integer as argument
for(auto& f : std::get<1>(functionTuple)) {
f(i);
i += 5;
}
return 0;
}
说了这么多,我要加一句警告。函数指针/对象和 lambda 只是一种工具。它们非常灵活和强大,因此可能会导致您陷入意外行为和错误的兔子洞。如果您不打算编写非常通用的算法并深入研究模板元编程,那么这个工具很可能不是完成这项工作的最佳选择。寻求不同的解决方案,例如 command pattern,可以让您的生活更轻松。