Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałGrażyna Mucha Został zmieniony 9 lat temu
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 << v << endl; v.Precyzja(k); // Przywróć domyślną precyzję // Wywołanie funkcji z klasy obiektu v, a nie do obiektu v cout << v << endl; } 1. Wykonują się na rzecz klasy, a nie obiektu. 2. Nie mają zmiennej this. Przykład PO5-9 / 29
10
Operator << Przykład Vec W("P");... cout << W << endl; ostream &operator<<(ostream &wy,const Vec &v) {int n=wy.precision(v.Pr); wy << v.naz << "=["; if(v.A) wy << ' ' << v.A[0]; for(int i=1; i<v.n; i++) wy << ", " << v.A[i]; return wy << " ]"<<setprecision(n); } Operatory wyprowadzania i wprowadzania definiuje się jako funkcje zaprzyjaźnione. Jeśli wektor nazywa się np. P, to wydruk planujemy w postaci: P=[ A 0, A 1, A 2,..., A n – 3, A n – 2, A n – 1 ] PO5-10 / 29
11
Operator >> istream &operator>>(istream &we, Vec &v) {int k = we==cin; if(k) cerr << "Wymiar " << v.naz << "= "; we >> v.n; delete []v.A; v.A = new(nothrow) double[v.n]; if(v.A==0) v.n=0; for(int i=0; i<v.n; i++) {if(k) cerr << v.naz << "[" <<(i+1)<< "]= "; we >> v.A[i]; } return we; } Jeśli wektor nazywa się np. P, to zaproszenia do wprowadzania danych planujemy tylko, gdy wprowadzamy z cin, w postaci: Wymiar P= P[1]= P[2]= Przykład Vec W("P");... cin >> W; PO5-11 / 29
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<0) return A[0]; 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<=n; i+ +, xp*=x) y+=A[i]*xp; Sposób 2 – schemat Hornera: y=(a n x n-1 + a n-1 x n-2 +...+ a 2 x + a 1 )x + a 0 = = ((a n x n-2 + a n-1 x n-3 +...+ a 2 )x + a 1 )x + a 0 =...= = ((...(a n x + a n-1 )x +...+ a 2 )x + a 1 )x + a 0 y 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... 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<<"Alokacja wektora"<<endl; return ::new(k); // alokacja k bajtów // potem aktywowany jest konstruktor // wynik jest typu Vec*, a nie void* } void Vec::operator delete(void *p) { cerr<<"Likwidacja wektora"<<endl; ::delete(p); } PO5-26 / 29
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
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.