ООП Перегруженные операции. Объекты-исключения

Содержание

Слайд 2

Перегруженные операции Перегруженные операции (формализм) С++ позволяет переопределить большинство операций языка

Перегруженные операции

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

при использовании с объектами конкретных классов эти операции выполнялись специфическим образом, через специально заданные функции.
Конкретно, можно перегружать следующие операции языка:
Последние четыре операции означают: индексацию, вызов функции, размещение в динамической памяти и освобождение памяти.
Для дальнейшего изложения, обозначим @ - некоторую перегружаемую операцию языка С++. Пусть x и y – объекты некоторых классов С++.
Перегрузка унарных операций.
@x – унарная операция над объектом x в префиксной форме интерпретируется как вызов функции-члена
x.operator@( ) без аргументов
или вызов friend-функции с именем
operator@( x ) с одним аргументом.
x@ – унарная операция над объектом x в постфиксной форме интерпретируется как вызов функции-члена
x.operator@( int ) , где аргумент типа int - фиктивный
или вызов friend-функции с именем
operator@( x, int) , где аргумент типа int – фиктивный.
.

+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |=
<< >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete

Слайд 3

Перегруженные операции Перегрузка бинарных операций. x @ y – бинарная операция

Перегруженные операции

Перегрузка бинарных операций.
x @ y – бинарная операция с объектами

x и y интерпретируется как вызов функции-члена
x.operator@( y ) с одним аргументом
или вызов friend-функции с именем
operator@( x , y ) с двумя аргументами.
Замечания к перегруженным операциям.
При перегрузке операций, полностью сохраняется синтаксис языка С++, в том числе приоритет и порядок выполнения операций.
Можно перегрузить операции new и delete и начать самостоятельно управлять процессами выделения и освобождения динамической памяти.
Можно перегрузить операцию индексации []. Индексы могут иметь любой тип (например, цвет, текст, др.). Это есть ассоциативные массивы.
Итераторы в контейнерах можно заменить «умными» перегруженными операциями «++» и «--», которые при обходе не позволяют выйти за пределы контейнера.
Можно переопределить операцию косвенной адресации объекта «->» для работы с «умными» указателями, которые при каждом обращении к объекту будут выполнять любую заданную вами работу.
Можно перегрузить операцию вызова функции, тогда запись вида <объект> ( <список-аргументов> ) будет рассматриваться как бинарная операция operator()(…).
Можно перегрузить операцию преобразования типа (собственный кастинг).
Слайд 4

Перегруженные операции Перегруженные операции (пример) Пример. Перегруженные операции для строк. #pragma

Перегруженные операции

Перегруженные операции (пример)
Пример. Перегруженные операции для строк.

#pragma warning( disable :

4996 4267 ) // выключим некоторые предупреждения
#include // понадобится для сцепления строк
#include // задействуем потоковый ввод/вывод
using namespace std; // пространство имен для потокового в/в
class str { // опишем класс «строки»
char* s; // указатель на символы
int n; // емкость буфера для хранения строки
public:
str() { n=1; s=NULL; } // 0-конструктор (по умолчанию)
str(const str&); // конструктор копирования
str(const char*); // конструктор общего вида
~str() { if(s) delete s; } // деструктор
str& operator~(); // операция инверсии строки
str& operator=(char*); // операция присваивания
str& operator=(str&); // операция присваивания
friend str& operator+(str&, str&); // операция сложения
friend str& operator+(str&, char*); // операция сложения
friend str& operator+(char*, str&); // операция сложения
friend istream& operator>>(istream&, str&); // операция ввода
friend ostream& operator<<(ostream&, str&); // операция вывода
};
Слайд 5

Перегруженные операции Конструкторы и инверсия строк // инверсия строки str& str::operator~()

Перегруженные операции

Конструкторы и инверсия строк

// инверсия строки
str& str::operator~() {
if(n>2) { // имеет

смысл для строк длиной больше 1 символа
char temp, *beg=s, *end=s+n-2; // рабочие указатели
while(beg temp=*beg; *beg++=*end; *end--=temp; }
}
return *this; // результат работы – сам объект
}

// конструктор общего вида
str::str(const char *text) {
s = new char[n=strlen(text)+1]; // получим память
strcpy(s, text); // небезопасная функция!
}

// конструктор копирования
str::str(const str &x) {
s = new char[n=x.n]; // получим память
strcpy(s, x.s); // небезопасная функция!
}

Слайд 6

Перегруженные операции Операторы присваивания // оператор присваивания char* str& str::operator=(char *text)

Перегруженные операции

Операторы присваивания

// оператор присваивания char*
str& str::operator=(char *text) {
if(s) delete[] s; //

освободим ранее использованную память
s = new char[n=strlen(text)+1]; // получим память
strcpy(s, text); // небезопасная функция!
return *this; // результат работы – сам объект
}

// оператор присваивания str
str& str::operator=(str &x) {
if(this != &x) { // не присваиваем ли объект самому себе?
if(s) delete[] s; // освободим ранее использованную память
s = new char[n=x.n]; // получим память
strcpy(s, x.s); // небезопасная функция!
}
return *this; // результат работы – сам объект
}

Слайд 7

Перегруженные операции Операторы сложения // дружественная функция: сложение двух объектов str

Перегруженные операции
Операторы сложения

// дружественная функция: сложение двух объектов str
str& operator+(str &x1,

str &x2) {
str *sum = new str; // новый объект – в нем будет сумма строк
sum->s = new char[ sum->n = x1.n + x2.n - 1]; // получим память
strcpy(sum->s, x1.s); // строка из первого объекта
strcat(sum->s, x2.s); // цепляем строку из второго объекта
return *sum; // результат – сцепленные строки
}

// дружественная функция: сложение объекта str + char*
str& operator+(str &x, char *text) {
str *sum = new str; // новый объект – в нем будет сумма строк
sum->s = new char[ sum->n = x.n + strlen(text) ]; // получим память
strcpy(sum->s, x.s); // строка из первого объекта
strcat(sum->s, text); // цепляем строку из второго объекта
return *sum; // результат – сцепленные строки
}

Слайд 8

Перегруженные операции Сложение, ввод и вывод строк // дружественная функция: сложение

Перегруженные операции

Сложение, ввод и вывод строк

// дружественная функция: сложение char* и

объекта str
str& operator+(char *text, str &x) {
str *sum = new str; // новый объект – в нем будет сумма строк
sum->s = new char[ sum->n = strlen(text) + x.n ]; // получим память
strcpy(sum->s, text); // строка из первого объекта
strcat(sum->s, x.s); // цепляем строку из второго объекта
return *sum; // результат – сцепленные строки
}

// дружественная функция: потоковый ввод объекта str
istream& operator>>(istream &z, str &x) {
char buf[BUFSIZ]; // рабочий буфер для ввода
z.get(buf,BUFSIZ,'\n'); // используем метод get() объекта z
x=buf; // операция присваивания для класса str уже определена
return z; // возвращаем объект класса istream
}

// дружественная функция: потоковый вывод объекта str
ostream& operator<<(ostream &z, str &x) {
return z<}

Слайд 9

Перегруженные операции Тестирование класса str // посмотрим, как работает класс str

Перегруженные операции

Тестирование класса str

// посмотрим, как работает класс str
void main(void) {
str

a, b="xxx", c; // обзаведемся тремя объектами
cin>>a; // потоковый ввод
c=a+b; // сложение объектов
cout<<(a+" "+b+" "+c)< cout<<~a<}