1 / 34

Предефиниране на операции

Предефиниране на операции. В C++ не могат да се дефинират нови оператори, но всеки съществуващ едноаргументен или двуаргументен оператор с изключение на :: , ?: , . , може да бъде предефиниран от програмиста, стига поне един операнд на оператора да е обект на някакъв клас .

hagen
Download Presentation

Предефиниране на операции

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Предефиниране на операции • В C++ не могат да се дефинират нови оператори, но всеки съществуващ едноаргументен или двуаргументен оператор с изключение на ::, ?:, ., може да бъде предефиниран от програмиста, стига поне един операнд на оператора да е обект на някакъв клас. • Например, възможно е да се предефинират операторите +, -, * и /, така че да могат да събират, изваждат, умножават и делят рационални числа. Тогава вместо sum(p, q), sub(p, q), mult(p, q) и quot(p, q) ще можем да пишем p+q, p-q, p*q и p/q, което е много по-удобно. • Предефинирането се осъществява с т. нар. операторни функции.

  2. Предефиниране на операции • Механизмът на предефиниране дава възможност за интерпретация на класовете като нови типове данни. • Ако aи b са два обекта от даден клас, то предефинирането на операция +позволява а+b да има смисъл. • Операцията може да се предефинира, ако в нея участва поне един обект от някакъв клас. Общ вид на операторна функция резултат_обект operatorоперация(параметри); или void за резултат

  3. Предефиниране на операции • Предефиниране с използване на независима приятелска функция • Предефиниране с използване на член - функция

  4. Предефиниране на операции • Предефиниране с използване на независима приятелска функция Общ вид за предефиниране class A { //член-данни public: //декларации на член-функции friend A operatorоперация(A x,A y); }; A operatorоперация(A x,A y) { //Тяло на приятелската функция } декларация на приятелска функция дефиниция на приятелска функция

  5. Предефиниране на операции • Предефиниране с използване на независима приятелска функция – пример за събиране на две рационални числа Декларация на клас рационално число #include <iostream.h> 1/3 class rac { private: int numer; int denom; public: rac(int=0, int=1); void read(); void print() const; friend rac operator+(rac const &, rac const &); }; rac::rac(int a, int b) {numer = a; denom = b; cout << "construct! \n"; } Декларация на приятелска функцияза предефиниране на + Дефиниция на конструктор

  6. Предефиниране на операции • Предефиниране с използване на независима приятелска функция – пример за събиране на две рационални числа Дефиниция на функцияза въвеждане на обект void rac::read() 2/3 { cout << "numer: "; cin >> numer; do { cout << "denom: "; cin >> denom; } while (denom == 0); } void rac::print() const { cout<<numer<<"/"<<denom<<endl; } rac operator+(rac const & r1, rac const & r2) { rac r(r1.numer*r2.denom + r2.numer*r1.denom, r1.denom*r2.denom); return r; } Дефиниция на функцияза извеждане на обект Дефиниция на приятелска функцияза предефиниране на +

  7. Предефиниране на операции • Предефиниране с използване на независима приятелска функция – пример за събиране на две рационални числа c = a + b; се интерпретира като c=operator+(a,b); void main() 3/3 {rac a(1,3), b(2,5); a.print(); b.print(); rac c; c=a+b; c.print(); c=a+b+c; c.print(); (a+b+c).print(); } construct construct 1/5 2/5 construct construct 11/15 construct construct 330/225 construct construct 7425/3375

  8. Предефиниране на операции • Предефиниране с използване на член - функция Общ вид за предефиниране class A { //член-данни public: //декларации на член-функции A operatorоперация(A x); }; A А::operatorоперация(A x) { //Тяло на член-функция за предефиниране } декларация на член- функция за предефиниране дефиниция на член- функция за предефиниране

  9. Предефиниране на операции • Предефиниране с използване на член – функция • Правило: Първият аргумент на член-функцията трябва да е обект на класа и при дефинирането на операторната функция не се задава като параметър. Ако това не е така, операцията не може да се предефинира като член-функция.

  10. Предефиниране на операции • Предефиниране с използване на член – функция примерза събиране на две рационални числа #include <iostream.h> 1/3 class rac {private: int numer; int denom; public: rac(int=0, int=1); void read(); void print() const; rac operator+(rac const &) const; }; rac::rac(int a, int b) {numer = a; denom = b; cout << "construct! \n"; } Декларация на клас рационално число Декларация на член функцияза предефиниране на + първи операнд се получава неявно от обекта, извикал функцията Дефиниция на конструктор

  11. Предефиниране на операции • Предефиниране с използване на член – функция примерза събиране на две рационални числа void rac::read() 2/3 { cout << "numer: "; cin >> numer; do { cout << "denom: "; cin >> denom; } while (denom == 0); } void rac::print() const { cout<<numer<<"/"<<denom<<endl; } rac rac::operator+(rac const & r1) const {rac r(numer*r1.denom + r1.numer*denom, denom*r1.denom); return r; } Дефиниция на функцияза въвеждане на обект Дефиниция на функцияза извеждане на обект Дефиниция на член функцияза предефиниране на +

  12. Предефиниране на операции • Предефиниране с използване на член – функция примерза събиране на две рационални числа void main() 3/3 {rac a(1,3), b(2,5); a.print(); b.print(); rac c; c=a+b; c.print(); c=a+b+c; c.print(); (a+b+c).print(); } c = a + b; се интерпретира като c=a.operator+(b); construct construct 1/5 2/5 construct construct 11/15 construct construct 330/225 construct construct 7425/3375

  13. Предефиниране на операции • За двата разгледани примера на предефиниране предаването на параметри е чрез псевдоним (т.е. по адрес), но връщането на резултат е по стойност (т.е. извършва се копиране). • За обекти с по-голяма дължина е препоръчително използване на псевдоними, както при предаване на параметри, така и при връщане на резултат. Декалрацияна приятелска функция friend point & operator + (point &a , point &b); . . . point & operator + (point &a); Декларация на член - функция friend point & operator + (const point &a , const point &b); . . . point & operator + (const point &a); За да не се променят параметрите

  14. Предефиниране на операции • Ако първият операнд в операцията е от базов тип, операцията не може да се предефинира с член-функция. • Предефинираните операции запазват броя на аргументите си.

  15. Предефиниране на операции Пример със съставно присвояване class test { int a,b; . . . void operator *=(test); void out() { cout << a<<“,”<<b<<“\n”; } }; void test :: operator *=(test x) test &test :: operator*=(test x) { a*=x.a; b*=x.b; }{ a*=x.a; b*=x.b; return *this; } void main() { test p; p*=5; p.out(); (p*=5).out(); } Или параметър (int x) За да няма грешка грешка – не връща резултат

  16. Предефиниране на операции • Пример за изчисляване на изрази: • 1) ob1+=10; • 2) ob3=10*++ob2; • 3) 5*оb3++ Където ob1,ob2,ob3 са обекти на клас правоъгълник. Операциите ++ (префикснаи постфиксна) и += да се предефинират чрез член-функции, а * - чрез приятелска функция.

  17. Предефиниране на операции Пример за изчисляване на изрази #include <iostream.h> 1/3 class rec { int w,l; public: rec(int a=0,int b=0) { w=a; l=b; } void out() { cout<<”правоъгълник:”<<w<<" "<<l<<"\n"; } rec &operator++() {w++; l++; return *this; } rec operator++(int n) { rec p=*this; w++; l++; return p; } предефиниране на ++ (префиксна) предефиниране на ++ (постфиксна)

  18. Предефиниране на операции Пример за изчисляване на изрази Декларация на член – функция за предефиниране на += void operator+=(int a); 2/3 friend rec &operator*(int a,const rec &x); }; Декларация на приятелска функция за предефиниране на *

  19. Предефиниране на операции Пример за изчисляване на изрази void rec::operator+=(int a) 3/3 { w+=a; l+=a; } rec &operator*(int a,const rec &x) { rec t; rec &p=t; t.w=x.w*a; t.l=x.l*a; return p; } void main() {rec ob1(1,2),ob2(5,6),ob3; ob1+=10; ob1.out(); ob3=10*++ob2; ob3.out(); (5*ob3++).out(); ob3.out(); } Дефиниция на член – функция за предефиниране на += Дефиниция на приятелска функция за предефиниране на * правоъгълник:11 12 правоъгълник:60 70 правоъгълник:300350 правоъгълник:61 71

  20. Предефиниране на операции Предефиниране на операция присвояване (=) • Операцията може да се предефинира само с член – функция. • За обекти, които нямат член-данни, указващи към динамична зона може да се използва операцията присвояване по подразбиране. • За обекти с член – данни, указващи към динамична памет е задължително включване в класа на операторна член-функция за предефиниране.

  21. Предефиниране на операции Предефиниране на операция присвояване (=) • За два обекта, дефинирани като: example a(5), b(3); • От прилагане на присвояване b=a; (виж Фиг. 1) следва: • преди присвояването съществуват два обекта (с техните динамични части, сочени от указател adr); • След присвояването (посимволно копиране), динамичната част на обекта b не се указва повече от b (указател adrна b сочи там, където и указателя adrна a). class example { int n; int *adr; public: ……..... }; Ако е дефиниран клас example с указател към динамична зона

  22. Фиг. 1Фиг. 2 Предефиниране на операции операцията присвояване се предефинира (Фиг. 2). Предефиниране на операция присвояване (=)

  23. Предефиниране на операции Предефиниране на операция присвояване (=) • Алгоритъм за предефиниране на операцията присвояване. • Ако a и bуказателите сочат един и същи обект, не се извършва действие. • Ако aи b указателите са различни, то: • Освобождава се динамичната зона, сочена от указателя на b; • Създава се нова динамична зона с размер, определен от броя елементи на а; • Копира се динамичната зона на а в новосъздадената.

  24. Предефиниране на операции Предефиниране на операция присвояване (=) #include <iostream.h> 1/3 class vect { int nbr; int *adr; public: vect(int ); ~vect(); vect &operator=(const vect &); }; vect::vect(int n) { adr=new int[nbr=n]; for(int i=0;i<nbr;i++) adr[i]=0; } vect::~vect() { delete adr; } Резултат – псевдоним (позволява многократно (верижно) присвояване) Резултат – обект (само просто присвояване) Декларация на операторна функция за присвояване

  25. Предефиниране на операции Предефиниране на операция присвояване (=) vect& vect::operator =(const vect &v)2/3 { if(this!=&v) { cout<<”изтриване на динамичен вектор\n”; delete adr; adr =new int[nbr =v.nbr]; for(int i=0;i<nbr;i++) adr[i]=v.adr[i]; } else cout<<”не се извършва действие\n”; return *this; }; Дефиниция на операторна функция за присвояване

  26. Предефиниране на операции Предефиниране на операция присвояване (=) void main() 3/3 { vect a(5),b(3),c(4); cout<<”присвояване a=b\n”; a=b; cout<<”присвояване c=c\n”; c=c; cout<<”присвояване a=b=c\n”; a=b=c; } присвояване a=b изтриване на динамичен вектор присвояване с = с не се извършва действие присвояване a=b = с изтриване на динамичен вектор изтриване на динамичен вектор

  27. Предефиниране на операции Предефиниране на операция присвояване (=) • Операторната функция за присвояване извършва аналогични действия на тези на копиращия конструктор. • Рaзликата е, че тя извършва тези действия върху съществуващ обект, а не върху токущо създаден. • Това налага предварително да бъде освободена динамичната памет, отделена за обекта.

  28. Предефиниране на операции Предефиниране на операция присвояване (=) • Копиращият конструктор (или т. нар. Конструктор за присвояване), операторна функция за присвояване и деструктора се наричат “голямата тройка” или “канонична форма на класа”. • Те са задължителни при класове, използващи динамичната памет.

  29. Предефиниране на операции Предефиниране на операция за достъп [ ] • Действията на операцията []задостъп до елемент от масив могат да се имитират с две член-функции, включени в класа. • Член – функция за въвеждане на стойност на дадена позиция pos • Член – функция за намиране на стойност от дадена позиция pos Въвежда 10 на позиция 0 в обекта а void range(int value, int pos); //a.range(10, 0); Извежда стойност от позиция 3 на обекта а int find(int pos); //cout << a.find(3);

  30. Предефиниране на операции Предефиниране на операция за достъп [ ] • Цел на предефинирането: a[i]да се използва като лява страна при присвояване. • Операцията []дава възможност за достъп до елемент на масив, намиращ се на позиция iот динамичната зона на обект от зададен клас. • Връщаната от операторната функция стойност трябва да се предава чрез псевдоним с цел операцията да се използва от лявата страна на оператор за присвояване. • Параметър на операторната функция е позицията i.

  31. Предефиниране на операции Предефиниране на операция за достъп [ ] #include <iostream.h> #define MAX 10 class vect { int nbr; int *adr; public: vect(); vect(int ); ~vect(); int & operator[ ](int); }; vect::vect() { adr= new int[nbr = MAX]; for(int i=0;i<MAX;i++) adr[i]=0; } Декларация на операторна функция [ ] Дефиниция на конструктор за създаване на временен обект

  32. Предефиниране на операции Предефиниране на операция за достъп [ ] vect::vect(int n) { adr = new int[nbr = n]; for(int i=0;i<nbr;i++) { cout<<"adr["<<i<<"]="; cin>>adr[i]; } } vect::~vect() { delete adr; } int & vect::operator[ ](int i) { return adr[i]; } Дефиниция на конструктор Дефиниция на операторна функция [ ]

  33. Предефиниране на операции Предефиниране на операция за достъп [ ] void main() { int i,n,s; do{ cout<<“въведи брой елементи:"; cin>>n; } while(n<1||n>MAX); vect a(n),b; for(i=0,s=0;i<n;i++) { b[i]=a[i]; s+=a[i]; } b[i]=s; for(i=0;i<n+1;i++) cout<<b[i]<<" "; } въведи брой елементи:3 adr[0]=22 adr[0]=33 adr[0]=44 22 33 44 99

  34. Предефиниране на операции Предефиниране на операция за достъп [ ] • Вторият операнд в операцията би могъл да се защити от промяна чрез: • За да се използва за константни обекти, член-функцията трябва да е от тип const. • Това налага предефиниране от вида: int &operator [ ](const int); int vect :: operator [ ]( int i) const//дефинира се втора{ return adr[ i ]; }//операторна функция в класа Резултатът не е псевдоним, т.е обекта само се консултира без да се модифицира

More Related