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