Вам не хватает лишней пары скобок при объявлении operator()
. Имя функции - operator()
, и ей все еще нужен список параметров после нее. Таким образом это должно выглядеть так:
int operator()(int a) {return a;}
Объекты функций (такие как функторы), как это, обычно используются, когда вы используете указатель на функцию. Однако у них есть преимущество в том, что они могут использовать наследование, и они также инкапсулируют состояние. Часто хорошо разработанные шаблоны классов или функций смогут использовать их практически взаимозаменяемо с указателями функций. Однако хороший оптимизатор обычно может генерировать лучший код при использовании объекта шаблона.
Для довольно сложного примера того, как вы можете использовать функциональные объекты, взгляните на шаблоны выражений.
Вот небольшой, несколько надуманный пример того, как они могут использовать наследование:
struct unary_int_func {
virtual int operator()(int i) = 0;
};
struct negate : public unary_int_func {
int operator()(int i) {return -i;}
};
struct one_plus : public unary_int_func {
int operator()(int i) {return i+1;}
};
void show_it(unary_int_func &op, int v) {
cout << op(v) << endl;
}
В этом случае мы создаем базовый класс с оператором в качестве чисто виртуальной функции. Затем мы получаем конкретные классы, которые его реализуют. Код, такой как show_it()
, может затем использовать любой экземпляр класса, производный от этой базы. Хотя мы могли бы просто использовать указатель на функцию, которая принимает int и возвращает int, это более безопасно. Код, который использует указатель функции, примет любой такой указатель на функцию, тогда как таким образом мы можем определить совершенно новую иерархию, которая отображает int в int:
struct a_different_base_class {
virtual int operator()(int i) = 0;
};
но экземпляры этого не будут взаимозаменяемы с экземплярами unary_int_func.
Что касается состояния, рассмотрим функцию бегущей суммы:
struct running_sum : public unary_int_func {
int total;
running_sum() : total(0) {}
int operator()(int i) {return total += i;}
};
int main()
{
running_sum s;
cout << s(1) << endl;
cout << s(2) << endl;
cout << s(3) << endl;
cout << s(4) << endl;
}
Здесь экземпляр running_sum
отслеживает общее количество. Он выведет 1, 3, 6 и 10. Указатели на функции не имеют такого способа сохранения состояния между различными вызовами. Страница SGI STL по функциональным объектам имеет аналогичный пример с моей текущей суммой, но показывает, как вы можете легко применить ее к ряду элементов в контейнере.