1 Wykład 5 Klasa Vec i jej operatory 1.Kategorie operatorów 2.Operatory ogólne - przykłady 3.Operatory specjalne [ ], ( ) oraz –> 4.Operatory new i delete 5.Konwertery PO5-1 / 29
2 Kategorie operatorów ogólne, specjalne, new i delete, konwertery. PO5-2 / 29
3 Kategorie operatorów Operatory ogólne, które albo są niestatycznymi metodami klasy, albo są funkcjami globalnymi, które mają co najmniej jeden argument typu obiektowego. Funkcje operatorowe można podzielić na cztery kategorie: 1. Operatory specjalne, które mogą być tylko niestatycznymi składowymi klasy. Są to operatory: = ( ) [ ] –>. 2. Operatory new i delete, które nie muszą być składowymi klasy, ani nie muszą posiadać argumentów typu obiektowego, a jeśli są funkcjami klasy, to są to funkcje statyczne. 3. Konwertery – bezparametrowe niestatyczne funkcje składowe klasy bez typu (nawet void), definiujące konwersje z typu klasy do innego typu. 4. PO5-3 / 29
4 Kategorie operatorów c.d. Operatory ogólne – mogą być wywoływane do obiektów, ale nie koniecznie. 1. Operatory specjalne – mogą być tylko wywoływane do obiektów, 2. Operatory new i delete – nie mogą być wywoływane do obiektów, 3. Konwertery – mogą być tylko wywoływane do obiektów (tak jak operatory specjalne). 4. PO5-4 / 29
5 Operatory ogólne c.d. Postacie operatorów 1 – argumentowych Postacie operatorów 2 – argumentowych Funkcje i zmienne statyczne - przypomnienie Przykłady operatorów > Przedrostkowy i przyrostkowy operator++ PO5-5 / 29
6 Postacie operatorów 1–argumentowych Niestatyczne metody klasy aktywowane do argumentu 1. Typ_wyniku Klasa::operator@( ); Typ_wyniku Klasa::operator@( ) const; Funkcje globalne z jednym argumentem typu obiektowego 2. Typ_wyniku operator@( Klasa ); Typ_wyniku operator@( Klasa& ); Typ_wyniku operator@( const Klasa& ); Np. Vec Vec::operator – ( ) const; Np. Vec operator – ( const Vec&); PO5-6 / 29
7 Postacie operatorów 2–argumentowych Niestatyczne metody klasy aktywowane do argumentu 1. Typ_wyniku Klasa::operator@( Typ_argumentu ); Typ_wyniku Klasa::operator@( Typ_argumentu ) const; Funkcje globalne z co najmniej jednym argumentem typu obiektowego 2. Typ_wyniku operator@( Typ_1, Typ_2 ); Np. Vec Vec::operator – ( const Vec& ) const; Np. Vec operator – ( const Vec&, const Vec& ); PO5-7 / 29
8 Funkcje i zmienne statyczne class Vec { //... static int Pr; //... public: //... Deklaracja funkcji w klasie static int Precyzja(int); //... }; int Vec::Pr=3; // Definicja zmiennej statycznej int Vec::Precyzja(int n) { int k = Pr; // zapamiętaj starą precyzję Pr = n; // ustaw nową precyzję return k; } PO5-8 / 29
9 Funkcje statyczne main( ) {int k = Vec::Precyzja(1); // Nowa precyzja dotyczy wszystkich obiektów klasy Vec v("V"); cin >> v; cout
10 Operator
11 Operator >> istream &operator>>(istream &we, Vec &v) {int k = we==cin; if(k) cerr
12 Operatory ++ operator++( ); operator++(int); Operator przedrostkowy (np. ++V) Typowy operator 1-argumentowy jest operatorem przedrostkowym np.: –x, *x, &x, oraz – –x, + + x. Ustawienie symbolu operatora za argumentem sugeruje, że mamy do czynienia z operatorem 2-argumentowym, np.: x–y, x*y, k&n. Tak też będziemy traktować przyrostkowe operatory – – i + +. x – – ??, x + + ??. Operator przyrostkowy (np. V ++) Nieużywane argumenty typu int PO5-12 / 29
13 Operatory ++ Vec &Vec::operator++( ) { // dodaje 1 do każdego elementu tablicy A for(int i =0; i < n; i++) A[i]++; return *this; } Vec &Vec::operator++(int) { // cyklicznie przesuwa elementy tablicy A o 1 w górę if(n >1) {double y = A[n-1]; for(int i = n-1; i>0; i--)A[i]= A[i-1]; A[0]= y; } return *this; } Operator przedrostkowy (np. ++V) Operator przyrostkowy (np. V++) PO5-13 / 29
14 Operatory specjalne Operator przypisania = Operator indeksacji [ ] Operator wywołania funkcji ( ) Operator –> PO5-14 / 29
15 Indeksacja - problemy Brak tablicy n naz A XXA[0]A[1]...A[i]...A[n–1]XX X Pr Zmienne wspólne wszystkim obiektom tej klasy n naz A = 0A = 0 W W[i]=X Indeks spoza zakresu A[0] A[1]...A[i]...A[n–1] Wersja 1 Wersja 2 W[i]=W.A[i] W PO5-15 / 29
16 Indeksacja double &Vec::operator[](int i)const {if(A==0 || i =n) return X; return A[i]; } Przykład Vec w;... w[0]=1; double &Vec::operator[](int i)const {if(A==0) return X; if(i=n) return A[n-1]; return A[i]; } Wersja 1 Wersja 2 Zmienna statyczna X PO5-16 / 29
17 Przykłady indeksacji y = W[i] z = P[i][j] Vec W,P[100]; int i,j; double y,z; Zmienna obiektowa Operator przeciążony w klasie Vec Nazwa tablicy (stała wskaźnikowa) Operator standardowy PO5-17 / 29
18 Obliczanie wartości wielomianu Oblicz: y = a n x n + a n-1 x n-1 +...+ a 2 x 2 + a 1 x + a 0 Sposób 1- bezpośredni: y=0; for(i=0, xp=1; i=0; i – –) y = y*x +A[i]; i=ny=a n i=n-1y= a n x + a n-1... PO5-18 / 29
19 Schemat Hornera y=0; for(i =n; i>=0; i – –) y = y*x +A[i]; i=ny=a n i=n-1y=a n x + a n-1 i=n-2y=a n x 2 + a n-1 x + a n-2 i=n-3y=a n x 3 + a n-1 x 2 + a n-2 x+ a n-3... i=1y=a n x n-1 + a n-1 x n-2 + a n-2 x n-3 + a n-3 x n-4 +… + a 2 x+ a 1 i=0y=a n x n + a n-1 x n-1 + a n-2 x n-2 + a n-3 x n-3 +…+ a 2 x 2 + a 1 x + a 0 PO5-19 / 29
20 Wywołanie funkcji Przykład Vec W; double x,y;... y = W(x); double Vec::operator( )(double x)const {double y=0; for(int i=n-1; i>=0; i--) y=y*x+A[i]; return y; } Jeżeli np. obiekt W przechowuje współczynniki wielomianu n – 1 stopnia i chcemy, aby wyrażenie W(x) obliczało wartość tego wielomianu w punkcie x, to możemy zdefiniować odpowiedni operator wywołania funkcji, który obliczy wartość y=A n – 1 x n – 1 +A n – 2 x n – 2 +A n – 3 x n – 3 +... +A 2 x 2 +A 1 x+A 0. PO5-20 / 29
21 Operatory –> KlasaA *operator->(); KlasaB *operator->(); KlasaB operator->(); KlasaB &operator->(); W klasie KlasaA operator –> może mieć jedną z poniższych postaci: Wyrażenie x –> y tworzy łańcuch wywołań: ((...((x.operator –>( )).operator –>( )).... ).operator –>( )) tak długo, aż wynikiem będzie wskaźnik na zmienną strukturową. Wtedy do tego wskaźnika wykonuje się standardowy operator –> z prawym argumentem równym y. x — > y (x.operator — >( )) — > y operator przeciążony (zwracający wskaźnik) operator standardowy PO5-21 / 29
22 Operatory –> KlasaB operator->(); KlasaB &operator->(); W klasie KlasaA operator –> ma jedną z postaci: Czyli gdy wynikiem x –>( ) jest obiekt B typu KlasaB, mamy: x — > y (B.operator — >( )) — > y operator przeciążony (zwracający wskaźnik) operator standardowy (x.operator — >( )) — > y B — > y PO5-22 / 29
23 Przykład struct Data { // sekcja publiczna short d, m, r; }; Niech będą następujące definicje klas Data i Osoba class Osoba { // sekcja prywatna char Imie[20],Nazw[40]; Data d_ur; //... public: //... Data *operator— >( ) { return &d_ur; } //... }; Osoba A; //... A — > r (A.operator — >( )) — > r operator standardowy (&(A. d_ur)) — > r Funkcja operator –> daje w wyniku wskaźnik na strukturę d_ur w obiekcie typu Osoba. PO5-23 / 29
24 Operatory new i delete PO5-24 / 29
25 Operatory new i delete void *operator new(size_t); void *operator new(size_t,Typ1,...,TypN); void operator delete(void*); Vec *q = new Vec; Vec *p = new (Arg1,...,ArgN)Vec; // powyżej aktywowane są konstruktory bezargumentowe // parametr typu size_t otrzymuje wartość sizeof(Vec) delete p; delete q; Nagłówki funkcji operatorowych Sposoby wywołania funkcji Vec *q = new Vec(10,"W"); // powyżej aktywowany jest konstruktor z argumentami lub PO5-25 / 29
26 Przykład void *Vec::operator new(size_t k) { cerr
27 Konwertery PO5-27 / 29
28 Konwerter Przykład Vec W; double y;... y = W; if( W )... Vec::operator double()const {double d=0; for(int i=n-1; i>=0; i--) d += A[i]*A[i]; return sqrt(d); } Jeżeli np. często obliczamy długość wektora, którego współczynniki przechowuje obiekt W, możemy zdefiniować konwersję z typu Vec do typu double PO5-28 / 29
29 Przykład 2 Gdybyśmy zdefiniowali jeszcze konwertery np.: Vec v,w;... if(w)...; Problemy Przykład 1 Vec v,w;... v = w+12.0; v = w+Vec(12.0); v = (double)w+12.0; ? Vec::operator double*()const {return A;} Vec::operator int()const {return n;} if( w.A)...; if((double)w)...; ? if( w.n)...; PO5-29 / 29