Как объявить указатель на функцию в C++

«Как объявить указатель на функцию в C++» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В C++ есть несколько способов объявить указатель на функцию.

1. Классический C-стиль:

// Указатель на функцию, принимающую int и const char*, возвращающую void
void (*printFunc)(int, const char*);

// Пример использования
void printMessage(int id, const char* msg) {
    std::cout << "[" << id << "] " << msg << std::endl;
}

int main() {
    printFunc = &printMessage; // Присваивание адреса функции
    printFunc(1, "Hello");     // Вызов через указатель
}

2. Псевдоним типа для удобства (typedef/using):

// С typedef (унаследовано из C)
typedef void (*PrintCallback)(int, const char*);
PrintCallback callback = printMessage;

// С using (предпочтительный современный способ C++)
using PrintHandler = void (*)(int, const char*);
PrintHandler handler = printMessage;

3. Современный C++ с std::function (более гибко):

#include <functional>
#include <iostream>

// std::function может хранить любой вызываемый объект
std::function<void(int, const char*)> funcObj;

funcObj = printMessage;          // Указатель на функцию
funcObj = [](int id, const char* msg) { // Лямбда-выражение
    std::cerr << "Error " << id << ": " << msg << 'n';
};

// Вызов одинаков для всех типов
funcObj(42, "Test");

Ключевые отличия:

  • Указатель в стиле C — легковесный, но не может хранить лямбды с захватом или функциональные объекты.
  • std::function — универсальная обертка с небольшим оверхедом, подходит для большинства случаев в современном C++.