Ответ
В 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++.
Ответ 18+ 🔞
Э, слушай, тут тема про указатели на функции в C++. Ну, ёпта, смотри, как будто на дворе 2002-й год, но до сих пор актуально, хоть и выглядит местами как манда с ушами.
Вот, блядь, классический C-стиль, от которого глаза на лоб лезут. Выглядит как хуй в пальто, но работает.
void (*printFunc)(int, const char*);
Смотри на эту хуйню: void (*printFunc). Это, блядь, указатель на функцию, которая принимает int и const char*, а сама нихуя не возвращает. Объявляешь, присваиваешь адрес функции — и поехали. Просто, но синтаксис — терпения ноль ебать, пока запомнишь, где звёздочку ставить.
Дальше идёт спасение для мозгов — псевдонимы. Раньше через typedef мучались, это как ебать копать лопатой. Сейчас, слава богу, есть using.
using PrintHandler = void (*)(int, const char*);
Вот это уже похоже на правду. Объявил один раз PrintHandler и юзаешь, где надо. Не нужно каждый раз этот ужас void (*)() писать, а то волнение ебать начинается.
А теперь, блядь, современная магия — std::function. Это уже не просто указатель, а, можно сказать, универсальная принималка всего, что можно вызвать. Лямбду с захватом? Запросто. Функтор? Без проблем. Обычную функцию? Да похуй, тоже влезет.
std::function<void(int, const char*)> funcObj;
funcObj = printMessage; // Старую функцию
funcObj = [](int id, const char* msg) { ... }; // Новую лямбду
Выглядит чисто и понятно. Правда, под капотом у него овердохуища всякой умной логики, так что если тебе на микросекунды считать — может, и не лучший выбор. Но для 99% случаев — то, что надо.
Короче, резюме:
- C-указатель — быстрый и голый, но с ним как с хитрой жопой — не угадаешь, когда ошибёшься в синтаксисе. Для лямбд с захватом — ни хуя себе, не подойдёт.
std::function— жирненький, универсальный, всех поимеет. Идеально, когда нужна гибкость и не нужно выжимать каждую каплю производительности. Главное — не выёбывайся и используй его, где можно.