Перегрузка оператора ()
Перегрузка функций обеспечивает механизм создания и выполнения вызовов функций с одним и тем же именем, но с разными параметрами. Это позволяет одной функции работать с несколькими разными типами данных (без необходимости придумывать уникальные имена для каждой из функций).
int subtract(int a, int b){ return a - b; } double subtract(double a, double b){ return a - b; }
В языке C++ операторы реализованы в виде функций. Используя перегрузку функции оператора, вы можете определить свои собственные версии операторов, которые будут работать с разными типами данных (включая пользовательские типы). Это называется перегрузкой оператора.
Перегрузка операторов позволяет нам определить самим тип параметров, при этом количество аргументов должно быть фиксировано. Например, оператор ==
всегда принимает два параметра (бинарный оператор), тогда как оператор !
всегда принимает один параметр (унарный оператор). Оператор ()
является особенно интересным, поскольку позволяет изменять как тип параметров, так и их количество.
Но следует помнить о двух вещах:
- Перегрузка круглых скобок должна осуществляться через метод класса.
- Оператор
()
является оператором вызова функции. В случае с классами перегрузка круглых скобок выполняется в методеoperator()(){}
(в объявлении функции перегрузки находятся две пары круглых скобок).
Перегрузка оператора ()
используется в реализации функторов (или «функциональных объектов») — классов, которые работают как функции. Преимущество функтора над обычной функцией заключается в том, что функторы могут хранить данные в переменных-членах (поскольку они сами являются классами). Вот пример использования простого функтора:
class Accumulator{ private: int mcounter = 0; public: Accumulator() { } int operator() (int i) { return (mcounter += i); } }; int main(){ Accumulator accum; cout << accum(30) << endl; // выведется 30 cout << accum(40) << endl; // выведется 70 }
Использование класса Accumulator выглядит так же, как и вызов обычной функции, но наш объект класса Accumulator может хранить значение, которое увеличивается.
Конечно, можно было просто создать функцию и использовать в ней статическую локальную переменную. Однако, поскольку функции представлены только одним глобальным экземпляром (т.е. нельзя создать несколько объектов функции), использовать эту функцию мы можем только для выполнения чего-то одного за раз. С помощью функторов мы можем создать любое количество отдельных функциональных объектов, которые нам нужны, и использовать их одновременно.