Иногда бывает нужно вызвать функцию по имени, представленном в виде текстовой строки. В URL'е это имя пришло, например. Или из текстового конфига вы его считали. Я долго искала какой-нибудь элегантный способ сделать это на С++, но ничего хорошего не нашла.
В JavaScript'е, например, для этого есть функция eval, которая пытается выполнить текстовую строку. Единственное решение, которое я нашла для C++: создавать некий массив, а лучше map с отображением символьного имени функции на указатель на нее.
void updateInfo()
{
...
}
map <string, void (*)()> mFunctions;
mFunctions["updateInfo"] = updateInfo;
//и так далее для всех функций, что нужно использовать
...
string sFunctionName;
...
//где-то там считали имя функции
mFunctions[sFunctionName]();//выполнили нужную функцию
mFunctions["updateInfo"]();//то же самое
И для каждой вновь появившейся функции придется руками этот массив править и перекомпилировать код.
Updated 11.04.2007[Сразу несколько человек в комментариях заметили, что есть способ лучше, предложенный Александреску в "Современном проектировании".]
Ну и ладно. Зато появился повод поговорить об указателях на функции.
Указатели на функцию - вещь интересная и полезная. Настолько полезная, что появился отдельный сайт, посвященный исключительно указателям на функции - www.function-pointer.org. Сейчас он редиректит вот сюда:
The Function Pointer Tutorials. Также в
C++ FAQ Lite есть раздел, посвященный указателям на функции. Я пробегусь по основным моментам, но все равно почитайте эти ссылки там много интересно и полезного.
Указатель на функцию может выглядеть например так:
//объявляется указатель под именем pt2Function
int (*pt2Function)(float, char, char);
Указатель на функцию-член класса может выглядеть так.
//объявляется указатель под именем pt2Member
int (TMyClass::*pt2Member)(float, char, char);
Указатель на константную функцию-член класса может выглядеть так.
//объявляется указатель под именем pt2ConstMember
int (TMyClass::*pt2ConstMember)(float, char, char) const;
(Все примеры из The Function Pointer Tutorials)И этот указатель на функцию можно всяко-разно использовать. Например, как я использовала в начале поста. Или его передать в функцию. И это получится уже коллбэк (
callback).
void sort_ints(int* begin_items, int num_items,
int (*cmpfunc)(int, int) );
(пример из Wikipedia)Это была объявлена функция сортировки, которая в для операции сравнения использует переданную cmpfunc.
Если вам вдруг нужно в качестве коллбэка передать нестатическую функцию-член класса, то, возможно, вы хотите странного. Но сделать это можно, вот
объяснение как это сделать из C++ FAQ Lite, вот
объяснение из The Function Pointer Tutorials.
Есть еще такое интересное понятие как
функтор (functor, сокращение от function object).
В C++ можно сделать так: объявить класс, в котором переопределен operator(). Работа с таким объектом выглядит как работа с функцией. Но при этом это полноценный объект, возможностей у него больше, чем у функции. Он, например, может хранить состояние. В нем можно опеределить данные, другие функции и с ними работать.
template <class Fun>
void foo(Fun f)
{
//...
f();
//...
}
Обычно под функтором понимается любой объект, с которым можно работать как с функцией, то есть в C++ функтором являются и объекты, с переопределенным operator(), и собственно функции. Но тут я встречала разночтения. Иногда, когда говорят про функторы, обычные функции туда не включают (этот подход мне больше по душе). А иногда еще встречается термин функционоид (functionoid), для функторов, не являющихся обычными функциями.
Сочетание функторов с темплейтами приводит к очень интересным возможностям. Обратите внимание, в приведенном выше примере f может являться как функтором, так и указателем на функцию.
Ссылки:
comp.lang.c++.moderated Newbie question about operator() and functors in generalФункторы очень интенсивно используются в STL, о чем рассказывается здесь:
Function Objects.
Очень хорошо, со всякими ссылками о функторах написано в
Function object, WikipediaУказатели на функции-члены и реализация самых быстрых делегатов на С++Указатели на функции члены класса