Можно ли в C++ реализовать массив функций? То есть, в массив можно записать функции a(), b() и c() (не сами функции, а операторы для их вызова), а затем вызывать их, как будет удобно. Если нет, то можно вызывать ту функцию, которая указана в аргументах?
Ответ
В современном c++ присутствуют удобные средства для оперирования функциями как функциональными объектами. Посмотрите functional, а именно std::function и std::bind. По указанным ссылкам также находятся очень хорошие примеры.
Разумеется в c++ можно работать и с голыми указателями на функции (свободные и функции-члены класса), но это не так удобно и просто. Особенно при построении пользовательского интерфейса.
Пример массива функций. В качестве массива используем стандартный контейнер std::vector. Ниже продемонстрировано как можно для более узкой сигнатуры функции использовать более широкое определение. Известно что вызывающая сторона ожидает сигнатуру void(int), а мы будем ей передавать void(int, int) и void(const std::string&, int, int)
#include
void a(int x, int y)
{
std::cout << "a(" << x << ", " << y << ")" << std::endl;
}
void b(int x, int y)
{
std::cout << "b(" << x << ", " << y << ")" << std::endl;
}
void c(const std::string& s, int x, int y)
{
std::cout << "c(" << s << ", " << x << ", " << y << ")" << std::endl;
}
int main () {
using namespace std::placeholders; // adds visibility of _1, _2, _3,...
std::vector
// создаем и помещаем в вектор функциональный объект, во время вызова необходимо передать один аргумент
functions.emplace_back(std::bind(a, _1, _1));
functions.emplace_back(std::bind(a, _1, 42));
functions.emplace_back(std::bind(a, _1, 100500));
functions.emplace_back(std::bind(b, _1, 42));
functions.emplace_back(std::bind(b, 42, _1));
functions.emplace_back(std::bind(c, "Hello world!", _1, 3));
int i = 0;
for (const auto& fn : functions) {
fn(i++);
}
return 0;
}
Вывод.
a(0, 0)
a(1, 42)
a(2, 100500)
b(3, 42)
b(42, 4)
c(Hello world!, 5, 3)
Еще один пример (взят с www.cplusplus.com):
// bind example
#include
// a function: (also works with function object: std::divides
struct MyPair {
double a,b;
double multiply() {return a*b;}
};
int main () {
using namespace std::placeholders; // adds visibility of _1, _2, _3,...
// binding functions:
auto fn_five = std::bind (my_divide,10,2); // returns 10/2
std::cout << fn_five() << '
'; // 5
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '
'; // 5
auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x
std::cout << fn_invert(10,2) << '
'; // 0.2
auto fn_rounding = std::bind
'; // 3
MyPair ten_two {10,2};
// binding members:
auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
std::cout << bound_member_fn(ten_two) << '
'; // 20
auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
std::cout << bound_member_data() << '
'; // 10
return 0;
}
Комментариев нет:
Отправить комментарий