Подтвердить что ты не робот

Ссылки на функции

Итак, я просто работал с указателями функций, и я помнил, что вы могли бы это сделать:

void Foo()
{
}

int main()
{
    void(& func)() = Foo;

    func(); //::Foo();
}

Очевидным преимуществом является то, что ссылки ссылаются на действительные объекты (если они не используются) или функционируют в этом случае.

Очевидными недостатками являются то, что вы не можете хранить массив ссылок и не можете использовать их для указателей функций-членов (по крайней мере, насколько я могу судить).

Мой вопрос: кто-нибудь их использует (т.е. ссылки на функции, а не указатели на функции), и если да, то в каких сценариях вы нашли их полезными/полезными?

Единственное место, где я могу видеть, что они полезны с летучей мыши, - это привязка ссылки на определенную функцию при работе с условной компиляцией.

4b9b3361

Ответ 1

Я использовал их раньше, чтобы добавить настройку в классы, передав их конструктору так, как шаблон стратегии

Ответ 2

Я думаю, что ваш пример использования довольно хорош. Потому что если вы будете использовать обычный указатель на функцию, а затем примените адрес-оператора, вы получите адрес указателя функции. Использование ссылки на функцию будет делать ожидаемую вещь, поскольку она возвращает указатель на саму функцию.

Я также не могу придумать много примеров. Удержание ссылок на функции, как вы указываете, имеет некоторые уродливые последствия. Другим возможным нежелательным последствием является, если он хранится как член класса, ваши объекты будут не назначаемыми, если вы не напишите свой собственный оператор = и воздержитесь от повторного назначения функции-ссылки.

Я думаю, что большинство применений ссылок на функции неявны, как и большинство применений ссылок на массивы - хотя, тем более, когда вы принимаете аргументы по ссылке:

template<typename T>
void do_something(T const& t) { ... }

Хотя прием массивов по ссылке имеет то преимущество, что не теряет информацию о своем размере, явное использование функций по ссылке явно не имеет преимуществ (по крайней мере, насколько я вижу). Я полагаю, что существование ссылок на функции в значительной степени оправдано идеалистическим представлением о ссылке как псевдонимами какого-либо объекта или функции вместе с тем фактом, что она позволяет передавать функции таким шаблонам, которые принимают их аргумент по ссылке.

Я бы, вероятно, не использовал их, если бы не стал им неизбежным. Константные указатели функций также предоставляют неприменимые вызывающие вызовы и, вероятно, избегают путаницы, когда другие программисты, которые, возможно, не очень хорошо знакомы с этими языковыми нишами, читают ваш код. Стоит отметить, что Vandervoorde и Josuttis также рекомендуют избегать их, чтобы уменьшить путаницу (в их книге С++ Templates - The Complete Guide).

Ответ 3

Ссылки функций, в отличие от указателей на функции, затрудняют их создание из недопустимого источника. Это полезно, если вы создаете оболочку вокруг библиотеки C - код С++ может принимать функцию обратного вызова по ссылке и передавать указатель на библиотеку C, если lbrary требует, чтобы переданный указатель не был NULL.

Это также удобный способ для псевдонима функции, особенно в С++ 11 с новым ключевым словом auto:

#include <iostream>
#include <typeinfo>

void f(int i, char c)
{
    std::cout << i << ' ' << c << std::endl;
}

int main()
{
    std::cout << typeid(f).name() << std::endl; //FvicE
    f(0, '1');

    void (*pf)(int, char) (&f); //ugly
    std::cout << typeid(pf).name() << std::endl; //PFvicE
    (*pf)(2, '3');
    pf(4, '5'); //works, but I don't recommend it

    void (&rf)(int, char) (f); //still ugly
    std::cout << typeid(rf).name() << std::endl; //FvicE
    rf(6, '7');

    auto &af (f); //pretty, but only works in C++11
    std::cout << typeid(af).name() << std::endl; //FvicE, same as above
    af(8, '9');
}

Ответ 4

Я использовал их в подключаемой системе, в которую можно было загрузить/выгрузить подключаемые DLL файлы во время выполнения. Я хотел бы найти известные символы в каждой DLL и передать их указателям на функции.

Ответ 5

в дополнение к использованию в качестве стратегии (как указал Роберт Гулд), я часто использую их в метапрограммировании точки входа (шаблона). Ссылка на функцию может быть легко подобрана параметром шаблона; с этого момента он может проходить через несколько слоев шаблонов (метапрограммирование). Конечно, это верно и для указателя функции, но ссылка является псевдонимом и, таким образом, более четко передает намерение.

Чтобы привести пример: при написании общей системы диспетчеризации команд для приложения многие команды должны быть объявлены как команды. Для клиентского кода мы можем использовать простую "функцию-строитель" в качестве интерфейсного. За кулисами эта функция-строитель подбирает фактическую сигнатуру функции в качестве параметра шаблона, выводит (путем метапрограммирования шаблонов) фактические значения параметров и возвращаемого типа и, возможно, выбирает подходящую специализацию для хранения "memento" и "undo functor". Эти функторы могут быть сохранены либо как указатели функций внутри, либо с помощью объектов функции boost или tr1 или С++ 11. Таким образом, можно создать вызов типа безопасной команды и "отменить".

Ответ 6

Я участвовал в проекте, который предназначен для реализации системы Object в C с использованием указателей функций и структур для реализации классов. Поскольку функции могут быть заменены, они могут реализовать своего рода систему наследования. К счастью, это усилие сломалось. Хотя задача была интересной, это была не очень хорошая идея для проекта (возможно, это не хорошая идея для чего-либо в производстве).

Я также использовал указатели на функции для подключаемой модульной системы на основе DLL, как было упомянуто ранее.