Вызов указателей на функции
Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 34 из 61.
Теперь, когда ты знаешь, как объявить function pointer и присвоить ему функцию, следующий шаг — фактически вызвать функцию через этот pointer.
Синтаксис прост. Вы используете указатель function так же, как вызывали бы обычную function:
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;
}Просто напишите имя pointer, а затем скобки, содержащие аргументы. C автоматически разыменовывает pointer и выполняет function, на которую он указывает.
Также можно использовать явный синтаксис разыменования с (*operation)(5, 3), но это необязательно и встречается реже. Обе формы дают одинаковые результаты.
Настоящая мощь проявляется, когда вы переназначаете pointer на разные functions:
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.
Задание
ЛегкоДавайте потренируемся вызывать functions через указатели и менять функцию, которая выполняется. Вы создадите простой калькулятор, способный переключаться между сложением и вычитанием во время выполнения.
Напишите программу, которая:
- Определяет две functions:
add: принимает два параметраintи возвращает их суммуsubtract: принимает два параметраintи возвращает результат вычитания second из first
- В
mainобъявляет указатель на function с именемcalc, который может указывать на functions, принимающие два параметраintи возвращающиеint - Считывает четыре inputs: два целых числа и два кода operation
- Для каждого кода operation:
- Назначает подходящую function указателю
calc(1 для add, 2 для subtract) - Вызывает function через указатель с двумя числами
- Выводит result
- Назначает подходящую function указателю
Вы получите четыре inputs: first число, second число, first код operation (1 или 2) и second код operation (1 или 2).
Ваш вывод должен содержать два result в отдельных строках: по одному для каждой operation, выполненной с использованием тех же двух чисел:
15
5В этом примере при inputs 10, 5, 1, 2: first operation (код 1) складывает 10 + 5 = 15, затем указатель переназначается, а second operation (код 2) вычитает 10 - 5 = 5.
Это демонстрирует, как одна и та же переменная-указатель может выполнять совершенно разную логику благодаря её переназначению между вызовами.
Попробуйте сами
#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;
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик7Указатели на функции
Объявление указателей на функцииВызов указателей на функцииTypedef для указателей на функцииПередача функций в качестве аргументовИтоги: Диспетчеризация калькулятора2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация кругаРеализация прямоугольникаПолиморфное использованиеКонтейнер фигурПотренируйтесь самостоятельно: Онлайн-компилятор C