Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции / Лекция 5-6_n — копия.docx
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
144.59 Кб
Скачать

Int main () {

Matrix matrix;

matrix (2, 3) = 3.6;

std::cout << matrix(2, 3);

return 0;

}

Результат выполнения программы

3.6

Выполним перегрузку оператора () еще раз, но уже без использования каких-либо параметров:

#include <iostream>

#include <cassert> // для assert()

class Matrix {

private:

double data [5][5];

public:

Matrix () {

// Присваиваем всем элементам массива значение 0.0

for (int row=0; row < 5; ++row)

for (int col=0; col < 5; ++col)

data[row][col] = 0.0;

}

double& operator() (int row, int col);

const double& operator() (int row, int col) const;

Void operator() ();

};

double& Matrix::operator()(int row, int col) {

assert(col >= 0 && col < 5);

assert(row >= 0 && row < 5);

return data[row][col];

}

const double& Matrix::operator()(int row, int col) const {

assert(col >= 0 && col < 5);

assert(row >= 0 && row < 5);

return data[row][col];

}

Void Matrix::operator()() {

// Сбрасываем значения всех элементов массива на 0.0

for (int row=0; row < 5; ++row)

for (int col=0; col < 5; ++col)

data[row][col] = 0.0;

}

Int main() {

Matrix matrix;

matrix(2, 3) = 3.6;

matrix(); // выполняем сброс

std::cout << matrix(2, 3);

return 0;

}

Результат выполнения программы:

0

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

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

В примере, приведенном выше, функцию очистки массива лучше было бы записать в виде метода clear() или erase(), поскольку matrix.erase() выглядит намного информативнее, нежели matrix().

Функторы в C++

Перегрузка операции () используется в реализации функторов (или «функциональных объектов») — это классы, которые работают как функции.

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

#include <iostream>

class Accumulator {

private:

int m_counter = 0;

public:

Accumulator () { }

int operator () (int i) { return (m_counter += i); }

};

int main() {

Accumulator accum;

std::cout << accum(30) << std::endl; // выведется 30

std::cout << accum(40) << std::endl; // выведется 70

return 0;

}

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

Вы можете спросить: «Зачем использовать класс, если всё можно реализовать и через обычную функцию со статической локальной переменной?». Можно сделать и через static, но, поскольку функции представлены только одним глобальным экземпляром (т.е. нельзя создать несколько объектов функции), использовать эту функцию мы можем только для выполнения чего-то одного за раз. С помощью функторов мы можем создать любое количество отдельных функциональных объектов, которые нам нужны, и использовать их одновременно.

Итак, перегрузка оператора () с двумя параметрами используется для получения доступа к двумерным массивам или для возврата подмножеств одномерного массива (два параметра будут конкретизировать условия отбора элементов подмножества).

Всё остальное лучше реализовать через отдельные методы с более информативными названиями, нежели через перегрузку оператора ().

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

Тест

Напишите класс, переменной-членом которого является строка. Перегрузите оператор () для возврата подстроки, которая начинается с индекса, указанного в значении первого параметра. Второй параметр должен указывать требуемую длину подстроки.

Подсказки:

Вы можете использовать индекс массива [] для доступа к отдельным символам строки.

Вы можете использовать оператор += для добавления чего-либо к строке.

Следующий фрагмент кода:

int main () {

Mystring string ("Hello, world!");

std::cout << string (7, 6); // начинаем с 7-го символа (индекса) и //возвращаем следующие 6 символов

return 0;

}

Должен выдавать следующий результат:

world!