Вызов указателей на функции
Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 34 из 61.
Теперь, когда вы знаете, как объявить указатель на функцию и присвоить ему функцию, следующим шагом будет фактически вызов функции через этот указатель.
Синтаксис прост — вы используете указатель на функцию точно так же, как если бы вы вызывали обычную функцию:
int add(int a, int b) {
return a + b;
}
int main() {
int (*operation)(int, int) = add;
int result = operation(5, 3); // Вызывает add(5, 3)
printf("%d\n", result); // Вывод: 8
return 0;
}Просто напишите имя указателя, за которым следуют круглые скобки с аргументами. C автоматически разыменовывает указатель и вызывает функцию, на которую он указывает.
Вы также можете использовать синтаксис явного разыменования с (*operation)(5, 3), но это необязательно и встречается реже. Обе формы дают идентичные результаты.
Настоящая мощь проявляется, когда вы переназначаете указатель на различные функции:
int subtract(int a, int b) {
return a - b;
}
operation = subtract;
result = operation(5, 3); // Теперь вызывает subtract(5, 3)
printf("%d\n", result); // Вывод: 2Та же самая переменная operation теперь выполняет совершенно другую логику. Эта возможность изменять поведение во время выполнения является основой полиморфизма в C.
Задание
ЛегкоДавайте попрактикуемся в вызове функций через указатели и переключении того, какая функция выполняется. Вы создадите простой калькулятор, который может переключаться между сложением и вычитанием во время выполнения программы.
Напишите программу, которая:
- Определяет две функции:
add— принимает два параметра типаintи возвращает их суммуsubtract— принимает два параметра типаintи возвращает разность первого и второго
- В функции
mainобъявляет указатель на функцию с именемcalc, который может указывать на функции, принимающие два параметра типаintи возвращающиеint - Считывает четыре входных значения: два целых числа и два кода операций
- Для каждого кода операции:
- Назначает соответствующую функцию указателю
calc(1 для сложения, 2 для вычитания) - Вызывает функцию через указатель с двумя числами
- Выводит результат
- Назначает соответствующую функцию указателю
Вы получите четыре входных значения: первое число, второе число, первый код операции (1 или 2) и второй код операции (1 или 2).
Ваш вывод должен содержать два результата на отдельных строках — по одному для каждой операции, выполненной с использованием тех же двух чисел:
15
5В этом примере при входных данных 10, 5, 1, 2: первая операция (код 1) складывает 10 + 5 = 15, затем указатель переназначается, и вторая операция (код 2) вычитает 10 - 5 = 5.
Это демонстрирует, как одна и та же переменная-указатель может выполнять совершенно разную логику путем ее переназначения между вызовами.
Шпаргалка
Чтобы вызвать функцию через указатель, используйте имя указателя, за которым следуют круглые скобки с аргументами:
int add(int a, int b) {
return a + b;
}
int main() {
int (*operation)(int, int) = add;
int result = operation(5, 3); // Вызывает add(5, 3)
printf("%d\n", result); // Output: 8
return 0;
}Вы также можете использовать синтаксис явного разыменования (*operation)(5, 3), но это не обязательно.
Указатели на функции могут быть переназначены для указания на другие функции во время выполнения программы:
int subtract(int a, int b) {
return a - b;
}
operation = subtract;
result = operation(5, 3); // Теперь вызывает subtract(5, 3)
printf("%d\n", result); // Output: 2Это позволяет одной и той же переменной-указателю выполнять различную логику путем ее переназначения между вызовами.
Попробуйте сами
#include <stdio.h>
// TODO: Определите здесь функцию add
// TODO: Определите здесь функцию subtract
int main() {
// Чтение входных данных
int num1, num2, op1, op2;
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &op1);
scanf("%d", &op2);
// TODO: Объявите указатель на функцию с именем 'calc', который может указывать на
// функции, принимающие два параметра типа int и возвращающие int
// TODO: Для первого кода операции (op1):
// - Назначьте соответствующую функцию для calc (1 для add, 2 для subtract)
// - Вызовите функцию через указатель и выведите результат
// TODO: Для второго кода операции (op2):
// - Переназначьте calc на соответствующую функцию
// - Вызовите функцию через указатель и выведите результат
return 0;
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик7Указатели на функции
Объявление указателей на функцииВызов указателей на функцииTypedef для указателей на функцииПередача функций в качестве аргументовИтоги: Диспетчеризация калькулятора2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация круга