1 Переопределение операций Макаревич Л. Г.. 2 Зачем нужна перегрузка операций? class Complex { double re; double im; public: Complex(double r=0, double.

Презентация:



Advertisements
Похожие презентации
Статические поля класса Статические поля хранят данные, общие для всех элементов класса. Статическое поле существует в единственном экземпляре для всех.
Advertisements

НГТУ, каф. ВТ Наследование в С++ Макаревич Л. Г.НГТУ, каф. ВТ Наследование в С++ Макаревич Л. Г.
Лекция 13. Введение в ООП. Часть 4 Красс Александр СПбГУ ИТМО, 2008.
Прикладное программирование кафедра прикладной и компьютерной оптики Полиморфизм.
Лекция 4. Введение в С++ Наследование, множественное наследование. Конструкторы, деструкторы. Виртуальные функции.
ООП Классы Данные отдельно, методы отдельно struct Node { Node* next; void* data; }; struct List { Node* first; int size; }; void* allocate() { … } void.
Инструкции C++ Условная инструкция Формат: if (условие) оператор; else оператор; Пример: if (i!=0) { if (j) j++; if(k) k++; else if(p) k--; } else i--;
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Лекция 12 Перегрузка операторов. Часть 2. Подбельский гл. 9.7, Страуструп гл. 11, Мейрс п. 11,15-17,19. Перегрузка копирующего конструктора T(const T&)
2. Классы.Полиморфизм.. Перегрузка функций void f(); void f(int value); void f(doublevalue); void f(int value, int nextValue); … f(); f(12); f(12.0);
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Лекция 10. Введение в ООП. Часть 3 Красс Александр СПбГУ ИТМО, 2008.
С++, начала ООП Семинар 1 Рябова Анна Сергеевна
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
Конструкторы и Деструкторы Конструкторы - функции, явно предназначенные для инициализации объектов Деструкторы - функция обратная конструктору для обеспечения.
Учебный курс Объектно-ориентированный анализ и программирование Лекция 7 Методы как средство реализации операций Лекции читает кандидат технических наук.
Лекция 6 Функции. Объявления и определения Объявление функции – указание имени функции, а также входных и выходных параметров Определение функции – указание.
Д.з Язык С++ - занятие 31. Задача 1: 1/1 + 1/3 + 1/5 … #include using namespace std; int main() { int n; cin >> n; double sum = 0;// Сумма for.
С++, ООП Семинар 2 Рябова Анна Сергеевна
Лекция 6 Функции. Объявления и определения Объявление функции – указание имени функции, а также входных и выходных параметров Определение функции – указание.
Транксрипт:

1 Переопределение операций Макаревич Л. Г.

2 Зачем нужна перегрузка операций? class Complex { double re; double im; public: Complex(double r=0, double i=0):re(r), im(i){} double getRe(){return re;} double getIm(){return im;} }; void main() { Complex c1(5,6); Complex c2(8,99); Complex c3; // c3 = c1 + c2; }

3 Что нельзя перегружать. – селектор члена структуры * - оператор доступа к члену по указателю :: - оператор разрешения видимости ?: - условный тернарный оператор

4 Различают: Бинарные Унарные Переопределяют: Функции-члены класса Внешние функции - операция, а w, x, y – объекты. эквивалентно y эквивалентно x (y) (x, y)

5 Перегруженные операции как функции-члены class Complex { double re; double im; public: Complex(double r=0, double i=0):re(r), im(i){} double getRe(){return re;} double getIm(){return im;} Complex operator + (const Complex & c) { Complex rez; rez.re = re + c.re; rez.im = im + c.im; return rez; } Complex operator – () const { Complex rez = *this; rez.re = -rez.re; return rez; } }; void main() { Complex c1(5,6); Complex c2(8,99); Complex c3; c3 = c1 + c2; // c3 = c1.operator + ( c2); c3 = -c2; // c3 = c2.operator – (); }

6 Перегруженные операции как внешние функции class Complex { double re; double im; public: Complex(double r=0, double i=0):re(r), im(i){} double getRe(){return re;} double getIm(){return im;} Complex operator + (const Complex & c) { Complex rez; rez.re = re + c.re; rez.im = im + c.im; return rez; } Complex operator – () const { Complex rez = *this; rez.re = -rez.re; return rez; } friend Complex operator – (const Complex & r1, const Complex & r2); friend Complex operator ! (const Complex & r1); }; Complex operator – (const Complex & r1, const Complex & r2) {Complex rez; rez.re = r1.re - r2.re; rez.im = r1.im - r2.im; return rez; } Complex operator ! (const Complex & r1) {Complex rez; rez.re = -r1.re; rez.im = r1.im; return rez; } void main() { Complex c1(5,6); Complex c2(8,99); Complex c3; c3 = c1 + c2; // c3 = c1.operator + ( c2); c3 = -c2; // c3 = c2.operator – (); c3 = c1 - c2; // c3 = operator - (c1, c2); c3 = !c2; // c3 = operator ! (c2); }

7 class Complex { double re; double im; public: Complex(double r=0, double i=0):re(r), im(i){} double getRe(){return re;} double getIm(){return im;} Complex operator + (const Complex & c) { Complex rez; rez.re = re + c.re; rez.im = im + c.im; return rez; } Complex operator – () const { Complex rez = *this; rez.re = -rez.re; return rez; } friend Complex operator – (const Complex & r1, const Complex & r2); friend Complex operator ! (const Complex & r1); Complex operator + ( double d) { Complex rez = *this; rez.re = -rez.re + d; return rez; } }; void main() { Complex c1(5,6); Complex c2(8,99); Complex c3; c3 = c1 + c2; // c3 = c1.operator + ( c2); c3 = -c2; // c3 = c2.operator – (); c3 = c1 - c2; // c3 = operator - (c1, c2); c3 = !c2; // c3 = operator ! (c2); с3 = с2 + 10; с3 = 10 + c2; } Вопрос «на засыпку» friend Complex operator – (const double r1, const Complex & r2); Complex operator – (const double r1, const Complex & r2) { Complex rez = r2; rez.re = rez.re + d; return rez; }

8 Оператор присваивания Присваивание по умолчанию Присваивание по умолчанию Не наследуется Не наследуется Определяется как функция-член класса Определяется как функция-член класса class String { char * str; int len; public: String() {str = NULL; len = 0; } String(char * s){len = strlen(s); str = new char[len + 1]; strcpy(str,s);} String(const String &s){len = s.len; str = new char[len + 1]; strcpy(str,s.str);} String & operator = (const String & s) { if ( this == &s) return *this; delete str; len = s.len; str = new char[len + 1]; strcpy(str,s.str); return *this; } }; void main() { String s1("abcdef"); String s2("1234"); String s3; s3 = s1; s2 = s2; s3 = s1 = s2; }

9 Вопрос «на засыпку» void main() { String s1("abcdef"); String s2("1234"); String s3; s3 = s1; s2 = s2; s3 = s1 = s2; String s4 = s1; } В чем разница?

10 Префиксные и постфиксные операторы class X { int value; public: X& operator ++() //префиксный { value++; return *this; } X operator ++(int) //постфиксный { X t = *this; value ++; return t; } }; void main() { X x; X y = x++; // y.value = ? X z = ++x; // z.value = ? }

11 Оператор индексирования Оператор бинарный a = b[10]; // a = b.operator[](10); //a = b[5][6]; - так нельзя Оператор бинарный a = b[10]; // a = b.operator[](10); //a = b[5][6]; - так нельзя Оператор – функция-член класса Оператор – функция-член класса Оператор индексирования ассоциируется с массивами Оператор индексирования ассоциируется с массивами class String { char * str; int len; public: String() {str = NULL; len = 0; } String(char * s){len = strlen(s); str = new char[len + 1]; strcpy(str,s);} String(const String &s){len = s.len; str = new char[len + 1]; strcpy(str,s.str);} String & operator = (const String & s) { if ( this == &s) return *this; delete str; len = s.len; str = new char[len + 1]; strcpy(str,s.str); return *this; } char & operator[] (int i) { if (( i >= 0 ) && ( i < (int)len )) return str[i]; } }; void main() { String s1("abcdef"); String s2("1234"); String s3; s3 = s1; s2 = s2; s3 = s1 = s2; char a = s3[2]; s3[2] = 's'; }

12 class ArrString { const int max; char ** pstr; int cur; public: ArrString(int j):max(j),cur(0){pstr = new char *[max];} void add(char * toAdd) { if ( cur < max) pstr[cur++] = toAdd; } char * operator[](int i) { if ((i >= 0)&&(i < cur)) return pstr[i]; return NULL; } int operator[](char * toFind) { for ( int i = 0; i < cur; i++) if ( strcmp(pstr[i], toFind)) return i; return -1; } }; void main() { String s1("abcdef"); String s2("1234"); String s3; s3 = s1; s2 = s2; s3 = s1 = s2; char a = s3[2]; s3[2] = 's'; ArrString arr(5); arr.add("123"); arr.add("qqqqqqqqq"); arr.add("aaaaaa"); int i = arr["123"]; char* p = arr[2]; }

13 Оператор вызова функций Оператор – функция-член класса Оператор – функция-член класса Функция может перегружаться, различие – в сигнатуре функций Функция может перегружаться, различие – в сигнатуре функций class A { int i,j; public: тип возврата operator()(список параметров); }; A a1; a1(список фактических параметров); // a1.operator()(список фактических параметров);

14 class String { char * str; size_t len; public: String() {str = NULL; len = 0; } String(char * s){len = strlen(s); str = new char[len + 1]; strcpy(str,s);} String(const String &s){len = s.len; str = new char[len + 1]; strcpy(str,s.str);} String & operator = (const String & s) { if ( this == &s) return *this; delete str; len = s.len; str = new char[len + 1]; strcpy(str,s.str); return *this; } char& operator[] (int i) { if (( i >= 0 ) && ( i < (int)len )) return str[i]; } char & operator()(int i) { return str[i];} char * operator()(int i, int j) {return &str[i+j];} }; void main() { String s1("abcdef"); String s2("1234"); String s3; s3 = s1; s2 = s2; s3 = s1 = s2; char a = s3[2]; s3[2] = 's'; s3(2) = 'b'; char ch = s3(1,1); }

15 Переопределение операции -> Оператор – функция-член класса Оператор – функция-член класса Возвращает указатель на структуру или объект класса Возвращает указатель на структуру или объект класса class YPtr { Y*py; public: YPtr(const int a) { py = new Y; py->a = py->b = a; } Y * operator ->() { return py; } ~YPtr(){delete py;} }; int main() { YPtr y(66); y->a = 99;// ( y.operator ->())->a y->b = 77; return 0; }

16 Перегрузка new и delete Оператор new должен иметь следующий прототип: void * new(size_t size, …); #include Оператор new должен иметь следующий прототип: void * new(size_t size, …); #include Оператор new может перегружаться Оператор new может перегружаться Операция new всегда статическая функция Операция new всегда статическая функция Оператор delete должен иметь прототип: void delete(void * ) Оператор delete должен иметь прототип: void delete(void * ) Оператор delete не может перегружаться Оператор delete не может перегружаться Оператор delete – статическая функция Оператор delete – статическая функция

17 class Blanks { public: Blanks(){} void *operator new( size_t st, char chInit ); }; void *Blanks::operator new( size_t st, char chInit ) { void *pvTemp = malloc( st ); if( pvTemp != 0 ) memset( pvTemp, chInit, st ); return pvTemp; } int main() { Blanks *a5 = new( 0xa5 ) Blanks; return a5 != 0; }

18 #include using namespace std; class Stack2 { int top_num; public: void * operator new(size_t s, int sz = 100) { return new char[s + sz* sizeof (int)]; } Stack2(){top_num = 1;} void push(int i){*((int *)this + top_num++) = i;} int pop(){return *((int *)this + --top_num);} }; class Stack1 { int * pst; int size; int count; public: Stack1(int s=100):size(s){pst = new int [size]; count = 0;} ~Stack1(){ delete pst;} void push( int value) { if ( count < size ) pst[count++] = value; return; } int pop() { return pst[--count];} }; void main() { Stack1 st1; //Stack2 st2; - нельзя, почему? Stack2 * st2 = new ( 20) Stack2; st1.push(6); st1.push(7); st1.push(2); st1.push(66); st2->push(6); st2->push(7); st2->push(2); st2->push(66); cout

19 class A { int* s1,* s2,* s3; public: void * operator new(size_t s, size_t n) { return ::new int[ s+3*n ]; } void operator delete(void * p) { ::delete p; } }; void main() { A * a1 = new(55) A; //… delete a1; }

20 class B { int i; public: int operator,(int k) { return i +k;} B(int _i){i = _i;} }; void main() { B b1(3); int k = (b1,8); }

21 Приведение типов С помощью конструктора С помощью конструктора С помощью оператора приведения типов С помощью оператора приведения типов

22 Приведение типов с помощью конструктора class A; class B { int b; public: B(int i){b = i;} friend class A; }; class A { int a; public: A(int i){a = i;} A(const B& b1){a = b1.b;} }; void main() { B bb(99); A aa = bb;}

23 Приведение типов с помощью операций приведения class A; class B { int b; public: B(int i){b = i;} friend class A; }; class A { int a; public: A(int i){a = i;} A(const B& b1){a = b1.b;} operator B(){B b1(a+99); return b1;} operator int(){ return 55*a;} }; void main() {B bb(99); A aa = bb; B x = aa; int k = aa; } operator тип (); operator тип (); Функция – член класса Функция – член класса Возвращает объект типа тип Возвращает объект типа тип

24 Указатели на элементы класса (методы) class Monstr { int health; int ammo; public: Monstr(int h, int a):health(h), ammo(a){} int get_health(){return health;} int get_ammo(){return ammo;} void f(int (Monstr::*pget)()) { (this->*pget)(); (*this.*pget)(); } }; void main() { Monstr Vasya; Monstr *p = new Monstr(2,100); Vasya.f(Monstr::get_health); int (Monstr::*pget)();// указатель на метод класса pget = &Monstr::get_health; Vasya.f(pget); int Vasin_health = (Vasya.*pget)(); int monstr_health = (p->*pget)(); } Нельзя определить указатель на статический метод класса Нельзя преобразовать указатель на метод к указателю на обычную функцию Указателю на метод можно присваивать адреса методов с определенным заголовком

25 Указатели на элементы класса (поля) class Monstr { public: int health; int ammo; public: Monstr(int h = 100, int a = 0):health(h), ammo(a){} int get_health(){return health;} int get_ammo(){return ammo;} void f(int (Monstr::*pget)()) { (this->*pget)(); (*this.*pget)(); } }; void main() { Monstr Vasya; Monstr *p = new Monstr(2,100); int (Monstr::*phealth) = &Monstr::health; cout health; ошибка cout *phealth; }