Передача функций в качестве аргументов
Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 36 из 61.
Одно из наиболее мощных применений указателей на функции — передача их в качестве аргументов другим функциям. Это позволяет внедрять пользовательское поведение в функцию, не изменяя её код: технику, которую иногда называют обратным вызовом.
Рассмотрим функцию, которая выполняет вычисление над двумя числами. Вместо того чтобы жёстко задавать операцию в коде, можно принять указатель на функцию, определяющий, какую операцию выполнять:
typedef int (*Operation)(int, int);
int compute(int a, int b, Operation op) {
return op(a, b);
}Функция compute не знает, выполняет ли она сложение, вычитание или что-то совершенно другое. Она просто вызывает любую переданную ей функцию:
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main() {
printf("%d\n", compute(5, 3, add)); // Вывод: 8
printf("%d\n", compute(5, 3, multiply)); // Вывод: 15
return 0;
}Обратите внимание, как одна и та же функция compute выдаёт разные результаты в зависимости от того, какую функцию мы передаём. Этот шаблон имеет фундаментальное значение для написания гибкого, повторно используемого кода. Вы один раз создаёте структуру, а пользователи вашей функции предоставляют необходимую им конкретную логику.
Задание
ЛегкоНапишите функцию apply_twice, которая принимает два целых числа и код операции, применяет операцию к числам дважды последовательно и возвращает итоговый результат.
Ваша функция получит код операции, определяющий, какую операцию использовать. Вы должны определить функции операций внутри своего решения и передать их вспомогательной функции compute, которая принимает указатель на функцию.
Примечание: нужны только функции. Тесты напрямую вызывают apply_twice и проверяют её возвращаемое значение, поэтому не считывайте ввод и ничего не выводите.
Требуемая структура:
- Определите
typedefс именемOperationдля указателя на функцию, которая принимает два параметра типаintи возвращает значение типаint - Определите две функции операций:
add(возвращает a + b) иmultiply(возвращает a * b) - Определите функцию
compute, которая принимает два целых числа и указатель на функцию типаOperation, а затем возвращает результат вызова операции - В
apply_twiceвыберите подходящую операцию на основе кода, затем дважды используйтеcompute: сначала с исходными числами, затем с результатом и вторым числом
Логика:
- Выберите функцию операции на основе
op_code(1 = add, 2 = multiply) - Вызовите
compute(a, b, operation), чтобы получить промежуточный результат - Вызовите
compute(intermediate, b, operation), чтобы получить итоговый результат - Верните итоговый результат
Параметры:
a(int): Первое числоb(int): Второе числоop_code(int): Код операции (1 для add, 2 для multiply)
Возвращаемое значение: Результат после последовательного применения операции дважды (int)
Пример: При a = 5, b = 3, op_code = 1 (add):
- Первое вычисление: 5 + 3 = 8
- Второе вычисление: 8 + 3 = 11
- Возвращаемое значение: 11
При a = 2, b = 4, op_code = 2 (multiply):
- Первое вычисление: 2 × 4 = 8
- Второе вычисление: 8 × 4 = 32
- Возвращаемое значение: 32
Попробуйте сами
int apply_twice(int a, int b, int op_code) {
// Напишите код здесь
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик7Указатели на функции
Объявление указателей на функцииВызов указателей на функцииTypedef для указателей на функцииПередача функций в качестве аргументовИтоги: Диспетчеризация калькулятора2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация кругаРеализация прямоугольникаПолиморфное использованиеКонтейнер фигурПотренируйтесь самостоятельно: Онлайн-компилятор C