Разделы презентаций


Перегрузка=,(),тип

Содержание

Картина присвоения напоминаетситуацию с инициализацией (даже хуже):до присвоенияs1 = s2;после присвоенияТак как компилятор выполняетпростое копированиеs1.line = s2.line;s1.len = s2.lenНельзя разбрасываться памятью!и оба объекта используютодну и ту же памятьи

Слайды и текст этой презентации

Слайд 12. Перегрузка операции =
Если объект использует динамическую
область, то для него

надо перегрузить
операцию ‘= ‘ - присвоение.
Рассмотрим почему.
Пусть заданы 2 объекта
String

s1, s2(“ФПМК”);
...
s1 = s2;
2. Перегрузка операции =Если объект использует динамическуюобласть, то для него надо перегрузитьоперацию ‘= ‘ - присвоение.Рассмотрим почему.Пусть

Слайд 2Картина присвоения напоминает
ситуацию с инициализацией (даже хуже):
до присвоения

s1 = s2;
после

присвоения

Так как компилятор выполняет
простое копирование
s1.line = s2.line;
s1.len = s2.len
Нельзя
разбрасываться

памятью!

и оба объекта используют
одну и ту же память

и



Картина присвоения напоминаетситуацию с инициализацией (даже хуже):до присвоенияs1 = s2;после присвоенияТак как компилятор выполняетпростое копированиеs1.line = s2.line;s1.len

Слайд 3Это недопустимо по следующим причинам:
1. Память в 80 байтов у

объекта s1 будет
«брошена» (считаться занятой);
2. объекты s1 и s2 будут

использовать одну и ту
же динамическую память по указателю line, что
приведет к тому, что любое изменение в поле
line объекта s1 приведет к изменению поля
line объекта s2 и наоборот;
3. при выходе из функции деструктор будет
пытаться дважды освободить одну и ту же
динамическую память: это фатальная ошибка!
Это недопустимо по следующим причинам:1. Память в 80 байтов у объекта s1 будет«брошена» (считаться занятой);2. объекты s1

Слайд 4В классах, где используется
динамическая память, операция ‘=’
обязательно перегружается.

В классах, где используетсядинамическая память, операция ‘=’обязательно перегружается.

Слайд 5Пример перегрузки операции = для класса String
String & String ::

operator =(String &s)
{
{ delete [ ] line;// Важно

освободить // динамическую память у *this
line = new char [(len = s.len) + 1]; // сразу // определим поле len
strcpy(line, s.line);
}
return *this;
}

if( this != &s) // на случай присвоения s = s

Пример перегрузки операции = для класса StringString & String :: operator =(String &s){  { delete [

Слайд 6Теперь присвоение s1 = s2 будет выполняться грамотно.

0
s1:
line
len

\0
...
Пустая строка из 80 байтов
s2:
4


line

len


Ф

П

М

К

\0

delete [ ] line; // 1)
line = new char [(len = s.len)+1]; // 2)
strcpy( line, s.line); // 3)


Ф

П

М

К

\0

1)

2)

3)

4

Основные действия
операции =



куча

Все неприятности исчезнут!

Теперь присвоение s1 = s2 будет выполняться грамотно.    0s1:linelen\0...Пустая строка из 80 байтовs2:

Слайд 7Конструктор копирования и операция присвоения =
String s(“УРА!”), r(“ФПМК”);
String p =

s;// работает конструктор копирования

r = s; // работает перегруженная

операция =
Конструктор копирования и  операция присвоения =String s(“УРА!”), r(“ФПМК”);String p = s;// работает конструктор копирования…r = s;

Слайд 8Отличие операции = и конструктора копирования
Оператор = выполняет 3 действия :
1.

Освобождает динамическую память у левого объекта ( её могло быть

меньше или больше, чем у правого);
2. берёт новую динамическую память размером её у правого объекта;
3. копирует поля правого объекта в поля левого.

Конструктор копирования выполняет 2 действия:
1. Берет динамическую память для левого
объекта размером её у правого;
2. копирует поля левого объекта в поля правого.

Конструктор копирования не может
выполнить освобождение памяти
у левого объекта, так как
у него её ещё и НЕ БЫЛО!

Отличие операции = и конструктора копированияОператор = выполняет 3 действия :1. Освобождает динамическую память у левого объекта

Слайд 9Если хотя бы один конструктор берёт динамическую память, то обязательно

возникают:

Деструктор
Конструктор копирования
Оператор =

Если хотя бы один конструктор берёт динамическую память, то обязательно возникают:ДеструкторКонструктор копированияОператор =

Слайд 103. Перегрузка операции ()
Если объект - матрица, то для

обращения к ее
элементам нельзя перегрузить [][].
В этом случае можно

использовать перегрузку
операции ().
class Matrix{ int **a, m, n;
public:
Matrix( int m1 = 1, int n1 = 1, int t = 0, int d = 10);
// конструктор с аргументами по умолчанию
~Matrix();
void Show(); // вывод матрицы
int & operator()(int, int);
...
};
3. Перегрузка операции ()  Если объект - матрица, то для обращения к ееэлементам нельзя перегрузить [][].

Слайд 11Конструктор
Matrix::Matrix(int mm, int nn, int t, int d)

// mm – строк, nn – столбцов, d -

диапозон
// t != 0 – генерировать случайные числа
{int i, j; m = mm; n = nn;
a = new int * [m];
for( i = 0; i < m; i++)
a[i] = new int [n];
if(t)
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
a[i][j] = rand()%d;
}
КонструкторMatrix::Matrix(int mm, int nn, int t, int d)    // mm – строк, nn –

Слайд 12Перегрузка ()
int & Matrix :: operator()(int i, int j)
{ if

(i < 0 || i >= m || j

0 || j >= n)
{puts("\n Значения индексов недопустимы. Выход.”);exit(1);}
return a[ i ][ j ];
}

Возвращаемое значение - ссылка int & - для того,
чтобы иметь возможность
менять значения элементов матрицы.

Перегрузка ()int & Matrix :: operator()(int i, int j){ if (i < 0 || i >= m

Слайд 13Пример использования
void main()
{ randomize();
Matrix A(3,4),B(3,3,1);

// A не инициализируется
// случайными числами,
// B – инициализируется
for ( int i = 0; i<3; i++)
B(i, i) = 1; // занесение 1 на главную диагональ
puts("\nB:“);
B.Show();
...
}
Пример использования 	void main(){ randomize(); Matrix A(3,4),B(3,3,1);

Слайд 14Замечание
Операция () - единственная,
которая может иметь
произвольное количество
аргументов( в частности

ЗамечаниеОперация () - единственная,которая может иметь произвольное количествоаргументов( в частности 0).

Слайд 15Пример
void Matrix:: operator()()
// очистить матрицу
{ int i, j;
for (

i = 0; i

0; j a[i][j] = 0;
}
Использование
Matrix B(5, 5);
B();

Примерvoid Matrix:: operator()()// очистить матрицу{ int i, j; for ( i = 0; i

Слайд 16Задание: определить деструктор класса Matrix
Matrix :: ~Matrix()
{ int i;
for(i =

0; i

Задание: определить деструктор класса MatrixMatrix :: ~Matrix(){ int i; for(i = 0; i

Слайд 174.Перегрузки операций + и +=


a += b; a = a

+ b;
a – = b; a = a – b;
a *=

b; a = a * b;
a /= b; a = a / b;
4.Перегрузки операций + и += a += b;		a = a + b;a – = b;		a = a

Слайд 184.Перегрузки операций + и +=
Ранее был рассмотрен пример перегрузки
операции

+=, меняющей первый операнд, то
есть *this. В классе String определим

операцию
+, которая не меняет ни первого операнда, ни
второго, как это принято при сложении базовых
типов данных.
Например, когда мы выполняем операцию
a+b,
то результат не записывается ни в a, ни в b,
если мы не выполним соответствующего
присвоения (например, a =a+b, b=a+b, c= a+b).
4.Перегрузки операций + и += Ранее был рассмотрен пример перегрузкиоперации +=, меняющей первый операнд, тоесть *this. В

Слайд 19Перегрузка +
Определение операции + может быть задано таким
образом
String

String :: operator + (const String &s)
{ String z( len

+ s.len + 1); // определим локальную строку // суммарной длины, пустую
strcpy( z.line, line); // перепишем в нее строку // первого операнда
strcat(z.line,s.line); // прибавим строку второго // операнда
z.len = strlen( z.line ); // определим длину результата
return z; // работает конструктор // копирования результата, // затем деструктор разрушает локальный объект z
}

Поэтому нельзя вернуть ссылку на локальный объект!

&

Работает конструктор с аргументом по умолчанию


Перегрузка +Определение операции + может быть задано такимобразомString   String :: operator + (const String &s){

Слайд 20Пример использования
void main()
{ String s1(“Объект ”), s2(“класса “),
s3(“ String”);
String

s4 = s1 + s2 + s3; // работают 2


// операции ‘+’ и конструктор копирования
s4.Print(); // вывод “Объект класса String”
}
Пример использованияvoid main(){ String s1(“Объект ”), s2(“класса “),	s3(“ String”); String s4 = s1 + s2 + s3;

Слайд 215. Перегрузка операции ++
Одноместная операция ++ перегружается
только в префиксной форме

(++i),
но может использоваться в постфиксном
виде (i++, компилятор дает об

этом
предупреждение), работая, однако, префиксно.
++i; и i++; будут действовать одинаково
и
x = ++i * 5 и x = i++ * 5 тоже одинаково!
5. Перегрузка операции ++Одноместная операция ++ перегружаетсятолько в префиксной форме (++i), но может использоваться в постфиксномвиде (i++,

Слайд 225. Перегрузка операции ++

Например, i = 5;

x=i++; // x =

5, i = 6, сначала x = i, затем i++
x=++i;

// x = 6, i = 6, сначала ++ i, затем x = i


5. Перегрузка операции ++Например, i = 5;x=i++; // x = 5, i = 6, сначала x =

Слайд 23Перегрузка ++ в классе String
Пример.
Операция ++ увеличивает коды символов
на 1.
String

String :: operator ++ ()
{ for(int i = 0; i

< len; i++)
line[ i ]++;
return *this;
}

Перегрузка ++ в классе StringПример.Операция ++ увеличивает коды символовна 1.String String :: operator ++ (){ for(int i

Слайд 24Использование:
void main()
{ String d(“12345*678”);
++d;
d.Print(); // d = ”23456+789”
}
Аналогично

перегружается операция --.

Использование: void main(){ String d(“12345*678”); ++d; d.Print(); // d = ”23456+789”}Аналогично перегружается операция --.

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

если мы хотим узнать код символа
char s = ‘*’,

то сделать это можно оператором
int k = (int) s;
Есть еще такая форма записи операции (тип)
тип(выражение).
Например,
float a = 3.76, b = 0.5, c = 1.22, d = 7;
int k = int (a*b - c*d / b);

В данных примерах эти преобразования
действуют и неявно (по умолчанию).

// int k = s;


// int k = a*b - c*d / b;

6. Перегрузка операции (тип)Операция (тип) используется дляпреобразования базовых типов данных.Например, если мы хотим узнать код символа char

Слайд 26Вернемся к классу String
Пусть задан такой фрагмент программы
String s1, s2(“Солнце!”);

char *str = ”Жарко!”;
Как отреагирует компилятор на следующие
присвоения?
s1 = str;

// char * ->String?
допустимо: преобразование из char* в String
выполняет конструктор String(char *) и в поле
s1.line перепишется строка «Жарко!», поле
s1. len =6.
Вернемся к классу StringПусть задан такой фрагмент программыString s1, s2(“Солнце!”); char *str = ”Жарко!”;Как отреагирует компилятор на

Слайд 27Итак, преобразование
конструктор(базовый тип)
базовый тип -------->абстрактный
выполняет

конструктор абстрактного
класса с аргументом базового типа
(если есть) по умолчанию.

Итак, преобразование     конструктор(базовый тип)базовый тип -------->абстрактныйвыполняет конструктор абстрактногокласса с аргументом базового типа(если есть)

Слайд 28Рассмотрим присвоение наоборот
str = s2; // ошибка: компилятор не знает,


какое поле из объекта s2 требуется
переписать в строку

str.
Другими словами, что понимается под
преобразованием
String -> char*
Поэтому, если требуется выполнять это
преобразование явно
str = (char *)s2;
или неявно
str = s2;

то надо определить, что понимается под
этим преобразованием.

И это знаем только
мы!

Рассмотрим присвоение наоборотstr = s2; // ошибка: компилятор не знает, какое поле из объекта s2 требуется переписать

Слайд 29Перегрузка операции преобразования
имеет общий вид
operator тип ()
{…}
В нашем случае, например,

её можно
определить следующим образом
String :: operator char *()
{return line;
}

Перегрузка операции преобразованияимеет общий видoperator тип (){…}В нашем случае, например, её можноопределить следующим образомString :: operator char

Слайд 30И присвоение
str = s2; // неявное String -> char *
или


str = (char *)s2; // явное преобразование
не вызовет ошибочного

сообщения
компилятора,
и *str = ”Солнце!”

Недостаток:
использование ограниченно из-за фиксированной
длины поля line в объекте s2, а также из-за того,
что указатели str и s2.line указывают
на одну и ту же динамическую память “Солнце!”

И присвоениеstr = s2; // неявное String -> char *или str = (char *)s2; // явное преобразование

Слайд 31Другие определения (char *)
String :: operator char*()
{ String *t

= new String ( *this );
return t->line;}
или
String

:: operator char *()
{ char *t = new char [ len+1 ];
strcpy(t, line);
return t;
}

Работает конструктор
копирования String(String &)


Недостаток: поля t->len и t->line будут брошены!

Так эффективнее всего.

Другие определения (char *)String :: operator char*() { String *t = new String ( *this );

Слайд 32А так вообще нельзя!
String :: operator char*()
{ String t

( *this ); // действует конструктор

// копирования
return t.line;}

t – локальный объект и при выходе он будет полностью разрушен и деструктором класса String от t->line в куче,
и стандартным деструктором от t.len, t.line!

А так вообще нельзя!String :: operator char*() { String t ( *this ); // действует конструктор

Слайд 33String -> int
Это преобразование из String в int можно
определить таким

образом
String :: operator int()
{return len;
}
Тогда можно выполнить присвоениe
int k =

s2; // работает operator int()
// k = 7; т.к. String s2(“Солнце!”); и s2.len = 7
String -> intЭто преобразование из String в int можноопределить таким образомString :: operator int(){return len;}Тогда можно выполнить

Слайд 34Итак
Преобразование

operator тип
абстрактный тип -------> базовый тип
задается

специальным оператором
(тип).
ИтакПреобразование              operator типабстрактный тип

Слайд 35Другое преобразование String ->int
Определим более полезное преобразование из
String в int:


преобразование числа-строки в форму целого
числа.
String :: operator int()
{ int k

= 0, i;
for(i = 0; i k = k*10 + line[i] - ‘0’;
return k;
}
Другое преобразование String ->intОпределим более полезное преобразование изString в int: преобразование числа-строки в форму целогочисла.String :: operator

Слайд 36Пример использования:
String d(“12345”); int m;
m = d;
m = 12345,

выполнено преобразование
числа-строки во внутреннюю форму
целого числа

Пример использования: String d(“12345”); int m;m = d; m = 12345, выполнено преобразованиечисла-строки во внутреннюю формуцелого числа

Слайд 37Преобразование float -> Complex
Определим классе Complex
class Complex { float

re, im;

public:
Complex( float a, float b)
{ re = a; im = b;}
Complex( float d = 0)
{ re = im = d;}
Complex operator +(Complex &);
...
};
Преобразование float -> ComplexОпределим классе Complex class Complex { float re, im;

Слайд 38float -> Complex
Будут справедливы такие действия
Complex c1, c2(5, 3); //

c1 = 0 +i*0

// c2 = 5 + i*3
float x = 3.3, y;
c1 = x; // c1 = 3.3 + i *3.3
Работает конструктор Complex( float ),
который определит и мнимую и вещественную
части комплексного числа равной x, т.е.
с1(3.3 + i*3.3)

Преобразование float -> Complex по умолчанию
выполняет конструктор Complex ( float d=0)

float -> ComplexБудут справедливы такие действияComplex c1, c2(5, 3); // c1 = 0 +i*0

Слайд 39Преобразование Complex -> float
Определим классе Complex
class Complex { float

re, im;

public:
Complex( float a, float b)
{ re = a; im = b;}
Complex( float d = 0)
{ re = im = d;}
Complex operator +(Complex &);
...
};
Преобразование Complex -> floatОпределим классе Complex class Complex { float re, im;

Слайд 40float -> Complex
Будут справедливы такие действия
Complex c1, c2(5, 3); //

c1 = 0 +i*0

// c2 = 5 + i*3
float x = 3.3, y;
c1 = x; // c1 = 3.3 + i *3.3
Работает конструктор Complex( float ),
который определит и мнимую и вещественную
части комплексного числа равной x, т.е.
с1(3.3 + i*3.3)

Преобразование float -> Complex по умолчанию
выполняет конструктор Complex ( float d=0)

float -> ComplexБудут справедливы такие действияComplex c1, c2(5, 3); // c1 = 0 +i*0

Слайд 41Complex -> float
Поэтому обратное преобразование
Complex -> float надо определить пользователю,
например,

таким образом
Complex :: operator float()
{ return re;}
Тогда оператор
y =

c2;
будет верным и y = c2.re = 5,
которую вернет
operator float ()
Complex -> floatПоэтому обратное преобразованиеComplex -> float надо определить пользователю,например, таким образомComplex :: operator float(){ return re;}Тогда

Слайд 42Преобразование абстрактный тип1 ---------> абстрактный тип2
Можно определить и такое преобразование

operator (абстрактный тип2)
абстрактный тип1 --------->

абстрактный тип2
Например, определим необычное преобразование
String -> Complex
String :: operator Complex()
{ Complex z(len); // действует конструктор Complex(float)
return z; }
Тогда следующий фрагмент кода будет выглядеть
совершенно нормально
String s(“Маша ела кашу”); Complex c; // c = 0 + i*0
c = s; // c = 13 + i*13

Complex( float d = 0)
{ re = im = d;}


Преобразование абстрактный тип1 ---------> абстрактный тип2Можно определить и такое преобразование       operator

Слайд 43Задание
Определите столь же необычное, но
полезное преобразование
Complex -> String !

ЗаданиеОпределите столь же необычное, нополезное преобразованиеComplex -> String !

Слайд 44Особенности перегрузки операции (тип)
Нет аргументов (операция чаще
используется неявно) и нет
возвращаемого

значения (даже void), т.к.
тип - это и есть возвращаемое значение;
2.

В теле операции обязательно должен
быть оператор return со значением, тип
которого является типом преобразования.
Особенности перегрузки операции (тип)Нет аргументов (операция чащеиспользуется неявно) и нетвозвращаемого значения (даже void), т.к.тип - это и

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика