Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
_24-29_ООП_MatiasRust_DC_CT_LE_LcMS.doc
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
122.88 Кб
Скачать

Причины использования перегрузки функций

Перегрузка функций улучшает удобочитаемость программ

Перегрузка функций C++ позволяет вашим программам определять несколько функций с одним и тем же именем. Перегруженные функции должны возвращать значения одинакового типа*, но могут отличаться количеством и типом параметров. До появления перегрузки функций в C++ программисты языка С должны были создавать несколько функций с почти одинаковыми именами.

Перегрузка операций – это возможность определения и выполнения стандартных операций C++ (+, -, * и т. д.) над классами, т. е. пользовательскими типами данных.

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

Перегрузка операций внутри класса

class MyClass {

int X;

void operator ++() {++X;} /* для унарной операции ++A единственным параметром будет объект this, поэтому у функции в скобках никакие параметры не указываются.*/

};

Перегрузка операций вне класса

class MyClass {

int X;

friend void operator ++(MyClass &A); // передача параметра по ссылке

};

void operator ++(MyClass &A){++A;}

Использование операций в программе в обоих случаях будет выглядеть одинаково:

int main(void){

MyClass X;

++X;

}

Основные правила перегрузки операций.

1. Вводить собственные обозначения для операций, не совпадающие со стандартными операциями языка С++, нельзя. Не все операции языка С++ могут быть перегружены. Нельзя перегрузить следующие операции:

. – прямой выбор компонента, .* – обращение к компоненту через указатель на него,

? : – условная (единственная тернарная) операция, :: – операция указания области видимости,

sizeof, # и ## – препроцессорные операции.

2. Каждая операция, заданная в языке, имеет определенное число операндов, свой приоритет и ассоциативность. Все эти правила, установленные для операций в языке, сохраняются и для ее перегрузки, т.е. изменить их нельзя.

– Любая унарная операция @ определяется двумя способами: либо как компонентная функция без параметров, либо как глобальная (возможно дружественная) функция с одним параметром.

– Любая бинарная операция @ определяется также двумя способами: либо как компонентная функция с одним параметром, либо как глобальная (возможно дружественная) функция с двумя параметрами. В первом случае x @ y означает вызов x.operator @(y), во втором – вызов operator @(x, y).

3. В языке С++ установлена идентичность некоторых операций, например, ++z – это тоже, что и z += 1. Эта идентичность теряется для перегруженных операций.

4. Функцию operator можно вызвать по ее имени, например, z = operator * (x, y) или z = x.operator *(y). В первом случае вызывается глобальная функция, во втором – компонентная функция класса X, и x – это объект класса X. Однако, чаще всего функция operator вызывается косвенно, например, z = x * y.

5. Перегрузка операций '++' и '--', записываемых после операнда (z++, z--), отличается добавлением в функцию operator фиктивного параметра int, который используется только как признак отличия операций z++ и z-- от операций ++z и --z.

Причины перегрузки конструктора копии

Если в классе не предусмотрен конструктор копии, компилятор генерирует конструктор копии по умолчанию, который производит простое копирование данных объекта в новый представитель класса. Если класс содержит какие-то указатели или ссылки, то такое копирование, скорее всего, будет бессмысленным или опасным.

Иногда, когда копирование объектов класса в принципе не может привести ни к чему хорошему, имеет смысл объявить конструктор копии (это может быть просто “пустышка”) в закрытом разделе определения класса. Тогда пользователь класса не сможет создавать копии существующих объектов.

Причины перегрузка оператора присваивания

Операция отличается тремя особенностями:

– операция не наследуется;

– операция определена по умолчанию для каждого класса в качестве операции поразрядного копирования объекта, стоящего справа от знака операции, в объект, стоящий слева.

– операция может перегружаться только в области определения класса. Это гарантирует, что первым операндом всегда будет леводопустимое выражение.

Бывают случаи, когда поразрядное копирование нежелательно. Например, использование предопределенной операции присваивания для классов, содержащих указатели в качестве компонентных данных, чаще всего приводит к ошибкам.

class String{

...

String &operator = (String &);

char *p; // указатель на строку

int len; // текущая длина строки

};

String &String::operator = (String &ob){

if (this == &ob) return *this;

if (len < ob.len){ // требуется выделить дополнительную память

delete [] p; p = new char[ob.len+1];

if (!p){ cout << "Ошибка выделения памяти\n"); exit(1); }

}

len = ob.len;

strcpy (p, ob.p);

return *this;

}

Производные классы. Механизмы наследования данных и методов базовых классов. Конструкторы и деструкторы производных классов. Полиморфизм и виртуальные функции, раннее и позднее связывание.

Производные классы

Общий формат производного класса:

class NewClass: Сlass1, Сlass2...{компоненты};

Механизмы наследования

Производный класс наследует все компоненты базовых классов со спецификаторами public (может использовать любой метод) и protected (методы этого класса и все от него производные), но не private.

В новом классе наследуемые компоненты имеют по умолчанию класс private (недоступны вне модуля). Статус доступа в наследуемых компонентах в новом классе можно изменить явным образом:

class NewClass: public Сlass1, private Сlass2...{компоненты};

// можно использовать только public и private, но не protected.

– public базовый класс: компоненты public базового класса становятся членами public производного класса. Компоненты protected базового класса становятся компонентами protected производного класса. Компоненты private базового класса недоступны для классов-потомков.

– private базовый класс: public и protected компоненты базового класса становятся private компонентами производного класса. Компоненты private базового класса остаются недоступны джля классов-потомков.