- •Принципы ооп:
- •Ооп, как средство обеспечения требований предъявляемых к современному программному обеспечению
- •Причины использования перегрузки функций
- •Конструкторы и деструкторы производных классов.
- •Полиморфизм и виртуальные функции, раннее и позднее связывание.
- •Форматирование данных, флаги и манипуляторы потоков.
- •Пример форматирования
- •Манипуляторы без параметров:
- •Int I, // параметр обычного типа
Причины использования перегрузки функций
Перегрузка функций улучшает удобочитаемость программ
Перегрузка функций 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 базового класса остаются недоступны джля классов-потомков.
