Przeciążenie operatorów

Podobne dokumenty
W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Zwracanie obiektu. Funkcja może zwracać obiekty: #include"stdafx.h #include <iostream> using namespace std; class samp { inti; public:

Dziedziczenie. Ogólna postać dziedziczenia klas:

it = 0; memset((void *)ptr, 0, items*sizeof(double)); cout << "Konstruktor sparametryzowany " << title << " adres: " << ptr << "\n";

Wykład 8: klasy cz. 4

PARADYGMATY PROGRAMOWANIA Wykład 3

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 4. Karol Tarnowski A-1 p.

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

TEMAT : KLASY DZIEDZICZENIE

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

Przeciążanie operatorów

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Wykład 5: Klasy cz. 3

Obsługa wyjątków. Język C++ WW12

Szablony klas, zastosowanie szablonów w programach

Laboratorium nr 10. Temat: Funkcje cz.2.

Programowanie, część I

Programowanie Obiektowe i C++

Lab 9 Podstawy Programowania

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Tbli Tablice obiektów biktó są tworzone dokładnie d tak samo, jak i tablice, składające się z elementów innego typu

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

Konstruktor kopiujacy

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

Programowanie w C++ Wykład 13. Katarzyna Grzelak. 4 czerwca K.Grzelak (Wykład 13) Programowanie w C++ 1 / 26

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Programowanie, część I

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Wykład 4: Klasy i Metody

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

Podstawy programowania skrót z wykładów:

PROGRAMOWANIE OBIEKTOWE W C++ cz. 2. Dziedziczenie, operacje wej cia-wyj cia, przeładowanie operatorów.

Programowanie obiektowe w C++ Wykład 12

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Programowanie 2. Język C++. Wykład 3.

Wstęp do Programowania 2

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Podstawy Programowania Obiektowego

Programowanie Obiektowe i C++

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

Język C++ umożliwia przeciążanie operatora, tzn. zmianę jego znaczenia na potrzeby danej klasy. W tym celu definiujemy funkcję o nazwie:

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

PARADYGMATY PROGRAMOWANIA Wykład 4

Wykład :37 PP2_W9

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Szablony funkcji i szablony klas

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 20 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 32

Algorytmy i Struktury Danych. Anna Paszyńska

C++ Przeładowanie operatorów i wzorce w klasach

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

PARADYGMATY PROGRAMOWANIA Wykład 2

Rozdział 4 KLASY, OBIEKTY, METODY

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Materiały do zajęć VII

4. Funkcje. Przykłady

operator zmiany znaku operatory mnożenia, dzielenia, dzielenia modulo operatory dodawania, odejmowania

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Plik klasy. h deklaracje klas

Podstawy Programowania Obiektowego

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Funkcje wirtualne. Wskaźniki do klas pochodnych są podstawą dla funkcji wirtualnych i polimorfizmu dynamicznego.

Język C zajęcia nr 11. Funkcje

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

.NET Klasy, obiekty. ciąg dalszy

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

#include "stdafx.h" #include <iostream> #include "windows.h" using namespace std;

Wprowadzenie do szablonów szablony funkcji

Język C++ zajęcia nr 2

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Wyliczanie wyrażenia obiekty tymczasowe

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Instrukcja do pracowni specjalistycznej z przedmiotu. Obiektowe programowanie aplikacji

KLASY cz4. Dorota Pylak. destruktory składowe statyczne przeciążanie operatorów. wskaźniki

Wprowadzenie do szablonów szablony funkcji

Wstęp do Programowania 2

Definiowanie własnych klas

Część 4 życie programu

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

Zaawansowane programowanie w C++ (PCP)

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

Transkrypt:

Przeciążenie operatorów W C++ można przeciążyć większość operatory tak, żeby wykonywali zadania, charakterystyczne dla danej klasy Po przeciążeniu odpowiednich operatorów można posługiwać się obiektami tych klas tak samo jak typami wbudowanymi C++. Operator można przeciążyć, tworząc funkcje operatora. Funkcje operatora wyznacza, jakie operacje na obiektach wskazanej klasy ma wykonywać operator. Do tworzenia funkcji operatora służy słowo kluczowe operator. Funkcja operatora może być składową klasy (a może i nie być). Najczęściej funkcja operatora, która nie jest składową klasy, jest funkcją zaprzyjaźnioną do tej klasy. Funkcja operatora składowej klasy zwrac_typ nazwa_klasy :: operator # (lista_argumentów) //operacje 1

Często typem wartości zwracanej funkcji operatora jest klas, dla którego ta funkcja jest wyznaczona. Znak # oznacza działanie operatora, który przeciążamy. Ograniczenia na przeciążenie operatorów: o Nie wolno zmieniać priorytet operatorów o Nie wolno zmieniać ilość operandów operatora o Nie wolno przeciążać operatory:. ::.*? Operator funkcje, za wyjątkiem operatora =, dziedziczy się klasą pochodną. Dla klasy pochodnej można przeciążyć dowolny operator, nawet te operatory, który już byli przeciążone w klasie bazowej. Funkcje operatory należy używać odpowiednio ich przeznaczeniu. Operatory funkcje nie mogą mieć parametrów domyślnych 2

Przeciążenie operatorów binarnych To jest taki operator, który ma dwa operandy Operator funkcje ma tylko jeden parametr dostanie ten obiekt, który jest umieszczony z prawej strony od operatora. Obiekt z lewej strony od operatora generuje wywołanie operator funkcji i będzie przekazany przez wskaźnik this. Dla napisania operatorów funkcji istnieje wielu sposobów Przykład W8_0_0. Przeciążenie operatorów + - * \ = dla klasy coord coord coord::operator + (const coord&praw) const coord ret; ret.x = x+praw.x; ret.y = y+praw.y; return ret; o Funkcja operator + zwraca obiekt typu coord. Wewnątrz tej funkcji 3

tworzymy pomocniczy obiekt res. Nadaję to możliwość używać ten operator w wyrażeniach złożonych jako a+b+c, dla tego że a+b+c = (a+b)+c i pierwszą sumę trzeba umieścić w pamięci tak, żeby nie zmienić żaden z składników. Dla tego i używamy tą funkcje, która zwraca obiekt. Prawy operand przekazujemy przez referencje, żeby przyspieszyć wykonanie i uniknąć tworzenia kopii obiektu, charakternego przy przekazani samego obiektu, a później zniszczenia tej kopii przez wywołanie destruktora. coord coord::operator -(const coord&praw) const coord ret; ret.x = x-praw.x; ret.y = y-praw.y; return ret; o Tu sytuacje jest podobna do przeciążenia operatora +, tylko trzeba dokładnie pamiętać o kolejności operandu z lewej strony (jest przekazany przez this) i z prawej strony (jest przekazany jako argument). 4

double coord::operator * ( const coord&praw) const /*================================================================== dot_prod ====================================================================*/ doubleret= 0.0; ret = x*praw.x+y*praw.y; return ret; o Wynikiem iloczynu skalarnego jest wartość rzeczywista operator funkcja zwraca wartość typu double. Pierwszy wektor (lewostronni operand) będzie pobrany przez wskaźnik this, a prawostronni operand przekazany jako parametr referencyjny. coord coord::operator * (const double alpa) const /*================================================================== mnozenie wektora przez skalar alpa ====================================================================*/ coord ret; ret.x = x*alpa; ret.y = y*alpa; return ret; o Wynikiem jest wektor (obiekt klasy coord, a skalar jest przekazywany jako parameter. 5

coord coord::operator / (const double alpa) const /*================================================ dzielenie wektora 2D przez skalar alpa =================================================*/ coord res; res.x = x/alpa; res.y = y/alpa; return res; o Wynikiem jest wektor (obiekt klasy coord, a skalar jest przekazywany jako parameter Jeśli prawy operand jest skalarem, to funkcji operatorowi trzeba przekazać skalar. Odwrotnie (lewy operand skalar) jest nie możliwe lewostronni operator generuje wywołanie operatora funkcji i przekazanie wskaźnika this powinien być obiektem klasy, odnośnie do której przeciążamy operator. 6

Przeciążenie operatora przypisania coord & coord::operator = (const coord &praw) /*================================================= Przyciazenie operatora przypisania: zwraca referencje do obiektu ==================================================*/ x = praw.x; y = praw.y; return *this; o Zwraca referencje do obiektu lewostronni operand jest L-value, w dodatek do tego po przypisani zwykłe się zmienia. Funkcja zwraca *this pobiera wartość po wskaźniku this i zwraca referencje. To nadaje możliwość używać kolejki a = b = c; To oznacza, że najpierw obiektowi b będzie przypisane wartości odpowiednich składowych obiektu c (b = c), a później wartości składowych obiektu b zastąpią odpowiedni wartości składowych obiektu a ( a = b). o Parametrem operator-funkcji = jest referencja do obiektu - operandu prawostronnego. Przekazywanie funkcji parametru referencyjnego nie powoduje tworzenia kopii obiektu jest istotnie szybsze od przekazywania obiektu i nie powoduje efektów ubocznych o Przykład W7 7

Przeciążenie operatorów relacyjnych i logicznych Operatory relacyjne i logiczne zwracają 0 (false) lub!0 (true), więc typem wartości zwracanej może być int lub bool. Operatory relacyjne i logiczne mogą się spotkać w wyrażeniach skomplikowanych, które zawierają dane innych typów Przykład W8_1_0 class coord double x; double y; public: coord(double xx, double yy) x = xx; y = yy; coord() x = 0.0; y = 0.0; void set(double xx, double yy) x = xx; y = yy; coord get() return *this; int operator == (coord &praw); //relacje == int operator > (coord &praw); //relacje > int operator && (coord &praw); //logichny koniunkcji int operator (coord &praw); //logichny alternatywy void disp(char *tit) cout << tit << ": " << x << " " << y << endl; ; 8

Przeciążenie operatora == odnośnie klasy coord. Lewostronni operand jest obiektem klasy coord, generuje wywołanie operator-funkcji i jest przekazywany przez this. Prawostronni operand jest również obiektem klasy coord i przekazywany przez referencje. Dane klasy są składowymi wektora, dwa wektora jest równe, jeśli są równe każda z odpowiednich składowych. int coord::operator == (coord &praw) return (x == praw.x && y == praw.y); Przeciążenie operatora > odnośnie klasy coord. Definiujemy dla obiektu danej klasy: relacje >, <, >=, <= są wyznaczone na podstawie porównywania module tych wektorów (norma 2 wektora). (Przecież to nie oznacza, że taka definicja jest jednoznaczna, można by było porównywać na podstawie normy lub inaczej to zależy od tego, którą normę dla podanego zagadnienia uważamy bardziej reprezentatywnej). int coord::operator > (coord &praw) double ro_lew, ro_praw; ro_lew = x*x+y*y; ro_praw = praw.x*praw.x+praw.y*praw.y; return (ro_lew > ro_praw); 9

Przeciążenie operatorów unarnych Funkcja-operator przy przeciążeni operatora unarnego nie potrzebuje przekazywania obiektu unarny operator ma tylko jeden operand, który generuje wywołanie tej funkcji i jest przekazywany przez this. Przykład W8_1_1 class scr_coord int x; int y; public: scr_coord(int xx, int yy) x = xx; y = yy; scr_coord() x = 0; y = 0; void set(int xx, int yy) x = xx; y = yy; scr_coord get() return *this; void disp(char *tit) cout << tit << ": " << x << " " << y << endl; scr_coord operator ++ (); //prefiksowa forma: ++ob; scr_coord operator ++ (int notused); //postfiksowa forma: ob++ ; 10

scr_coord scr_coord::operator ++ () //prefiksowa forma ++ob - najpierw inkrementujemy // - poznej - przepisyjemy ++x; ++y; return *this; scr_coord scr_coord::operator ++ (int notused) //postfiksowa forma ob()++ - najpierw przypisujemy, //pozniej - inkrementujemy //uwaga! dane klasy scr_coord nie //zawieraja wskaznikow, plikow,... //dla tego mozna nie przeciazac konstruktor kopiujacy //(inicjowanie obiektem *this, funkcje zwraca obiekt klasy) //i nie przyciazac operator = (ob = ob1++;) scr_coord ret = *this; x++; y++; return ret; Operator ++ zwiększa wartości składowych obiektu zmienia obiekt. Oprócz tego, może być używany w postaci ob = ++ob1. Dla tego zwraca obiekt klasy, żeby można było wykorzystywać w konstrukcjach złożonych. 11

Przy prefiksowej formie operatora ++ lista argumentów formalnych jest pusta. Dla odróżnienia od formy prefiksowej forma postfiksowa ma argument int notused. Dla zachowania analogii z typami danych wbudowanych C++ przy użyci operatora ++ w kontekście ob = ob1++ dane obiektu ob nie powinni być zmienione. Dla tego postfiksowa forma operatora ++ zwraca obiekt, który zawiera dane przed inkrementowaniem. Operator-funkcje zaprzyjaźnione Istnieje możliwość przeciążenia operator-funkcji odnośnie klasy podanej, używając nie funkcje - metodą klasy, a funkcje zaprzyjaźnioną. Dla funkcji zaprzyjaźnionych wskaźnik this nie jest przekazywany musimy przekazywać jawnie i operator lewostronni, i operator prawostronni (dla operatorów binarnych). Inne cechę przeciążenia operatorów dla funkcji zaprzyjaźnionych pozostają takie same, jak i dla operator funkcji składowych klasy. 12

Dla przeciążenia operatora przypisania (=), a również operatora [ ], można używać tylko operator funkcje składową klasy (nie wolno używać operator funkcje zaprzyjaźnione do klasy). Deklaracja operator-funkcji zaprzyjaźnionej do klasy: friend wart_zwrac operator # (typ_lew lewy_operand, typ_praw prawy operand); Definicja operator-funkcji nie składowej klasy (operator binarny): wart_zwrac operator # (typ_lew lewy_operand, typ_praw prawy operand) W liście argumentów na pierwszym miejscu stoi lewostronni operand, a na prawym prawostronni. Dla operator-funkcji składowych klasy lewostronni operand jest przekazywany niejawnie przez wskaźnik this to oznacza, że lewostronni operand mysi mieć typ obiektu klasy. Na przykład: 13

class coord double x, y; public: coord operator + (double aa); ; coord coord::operator + (double aa) coord tmp; tmp.x = x+aa; tmp.y = y+aa; return tmp; int main() coord ob( ), res; res = ob + 10.0; res = 10.0 + ob; return 0; //OK, lewostronni operand ma typ coord //!OK, lewostronni operand nie jest typu coord 14

Ten problem może być rozwiązany przy użycji operator-funkcji zaprzyjaźnionych do klasy: class coord double x, y; public:. coord operator + (double aa); friend coord operator + (double lew, coord praw); ; coord operator + (double lew, coord praw) coord tmp; tmp.x = lew+praw.x; tmp.y = lew+praw.y; return tmp; int main() coord ob( ), res; res = ob + 10.0; res = 10.0 + ob; return 0; //OK, lewostronni operand ma typ coord //!OK, lewostronni operand nie jest typu coord Przykład W8_1_2. 15

Przeciążenie operatorów unarnych ++, -- na podstawie operator-funkcji zaprzyjaźnionych. Operatory ++, -- zmieniają wartości składowych obiektu. Dla przyspieszenia działania warto przekazywać referencje do obiektów: class scr_coord int x; int y; public: friend scr_coord operator ++ (scr_coord &ob); //prefiksowa forma friend scr_coord operator ++ (scr_coord &ob, int notused); //postfiksowa forma: ob++ ; Przeciążenie operatora indeksu tablicy [ ]. W języku C++ operator [ ] jest operatorem binarnym, przy czym jego można przeciążyć tylko jako funkcjeskładową klasy. zwrac_typ & nazwa_klasy :: operator [ ] (int indeks) //.. Operator [ ] zwraca element tablicy o podanym indeksie typ wartości zwracanej referencje do zwracanego obiektu. To nadaje możliwość używać ob[i] = z lewej strony operatora przypisania. 16

Lewostronni operand obiekt klasy, prawostronni indeks elementu tablicy Przykład: class s_array double *arr; public: s_array(int ndim); //konstruktor: alokuje pamięć dla tablicy arr o ndim elementów ~s_array(); //destruktor: zwalnia tą pamięć double &operator[](int i); void put(double a, int i) arr[i] = a; double get(int i) return arr[i]; ; double & s_array::operator [] (int i) return arr[i]; int _tmain(int argc, _TCHAR* argv[]) int ii; s_array aa(10); //teraz można odwołowywac do obiektu klasy s_array tak, jako do zwyklej tablicy aa[0] = 100.0; //tu [] jest użyty jako L-value aa[1] = aa[0]+100.0;. 17

Bezpieczna tablica - przykład W8_1 Tablica bezpieczna wymaga dość istotnego nakładu pracy, powoduje to znaczny spadek wydajności obliczeń. Dla tego w języku C++ granicy tablic nie są kontrolowane. Przecież w wersji debagowej można zastosować tablicy bezpieczne, a w wersji release usunąć ich. Przeciążenie operatorów new, delete. Przeciążenie lokalne funkcje-operatory new, delete są składowymi danej klasy. Obiekty danej klasy będą alokowane przez przeciążone operatory new, delete, a obiekty innych typów - przez standardowe operatory new, delete. Przeciążenie globalne - funkcje-operatory new, delete są zdefiniowane w pliku globalnie poza deklaracją jakieś klasy (prototypy trzeba usunąć). Obiekty wszystkich typów będą alokowane przez przeciążone operatory new, delete. Przykład W8_3. 18