**Полиморфизм** - способность одного и того же оператора (команды, функции, действия и т. д.) приобретать различные смыслы (значения) в зависимости от обрабатываемых данных. 1. Перегрузка - преобразование типов данных 2. Перегрузка функций 3. Перегрузка операторов ## 1. Перегрузка - преобразование типов данных Перегрузка - преобразование типов данных необходимо для совмещения и использования разных типов данных. ```cpp int + float (5 + 6.7) float + float (5.0 + 6.7) float i = 11.7; int i = 11; ``` Для преобразования типов классов к более узкому типу данных используются специальная компонентная функция `operator type()`. Функция не имеет параметров и возвращаемого типа. ## 2. Перегрузка функций #### Алгоритм выбора перегруженной функции 1. Найти среди этих перегруженных функций ту, у которой есть совпадение по количеству параметров 2. Проверяется строгое соответствие типу данных 3. Если типы не совпадают, компилятор применяет стандартное повышение типа 4. Стандартное преобразование типа (`void* -> тип*`) 5. Компилятор будет пробовать применять определенные пользователем преобразования типов данных 6. Компилятор будет проверять, есть ли функция `void f(...)` - функция с переменным числом параметров Если ничего не сработает - будет синтаксическая ошибка ## 3. Перегрузка операторов Перегружать можно и бинарные, и унарные операторы. Перегружать их можно и компонентными, и внешними функциями. Параметрами у этих функций должны быть либо объекты, либо ссылки на них, но не указатели. Можно перегружать только нестатической компонентной функцией: `=, [], (), ->, new, delete`. Перегружать нельзя (и не нужно): `::, sizeof, ?:, ., .*` ```cpp pixel& operator=(const pixel& other) ``` Если в классе есть копирующий конструктор, то в этом классе необходимо иметь функцию, содержащую перегрузку оператора присваивания. ```cpp pixel operator+(pixel b); friend pixel operator+(pixel a, pixel b); pixel& operator++(); pixel& operator++(int); pixel t1, t2, t3; t3 = t1 + t2; t1.operator+(t2); operator+(t1, t2); ``` ```cpp class vect { private: float* p; int k; public: float& element(int i); }; vect v1, v2, v3; v1.element(3); v2.element(10); v3.element(k); ``` ```cpp class matrix { private: float** p; int k1, k2; public: float& element(int i, int j); float& operator()(int i, int j); } float& matrix::operator()(int i, int j) { return p[i][j]; } matrix m1, m2, m3; m1.element(5, 7); m1(5, 7); m2(10, 11); ``` ## Дружественные функции `friend f()` - **дружественная функция**. Она даёт доступ к приватным элементам класса. Используется в том числе для перегрузки бинарных операторов. ```cpp class A { public: void f_A(); friend void f(); }; class B { public: void f_B(); friend void f(); friend void A::f_A(); friend class C; }; ```