03-PreklapanjeOperatora

Report
Preklapanje operatora





Tipovi operatora
Tipovi podataka i efekat operatora
Pojam preklapanja operatora
Operatorske funkcije
Konverzije tipova

Korišćenjem operatora
Matrix a, b, c;
Matrix d = c * (a + b);

Bez operatora, korišćenjem metoda
Matrix a, b, c;
Matrix d = c.Multiply(a.Add(b));

Dvije kategorije tipova
◦ Value types
 Prosti tipovi (int, byte, float...) i strukture
 Direktno sadrže vrijednost
 Vrijednost se čuva u stack dijelu memorije
◦ Reference types
 Klasni tipovi
 Sadrže referencu na vrijednost (adresu memorijske
lokacije)
 Vrijednost se čuva u managed heap dijelu memorije

Zavisno od kategorije tipa, razlikuje se način
izvršavanja operacija nad podacima tog tipa
Type
Value Type
Reference Type
Value Types
Built-in Type
User-Defined

int

enum

float

struct
// i, j su tipa int
i = 20;
j = i;
i++;
j+=2;
Console.WriteLine(i);
Console.WriteLine(j);

Koje vrijednosti se ispisuju?

Kreiranje varijabli
coordinate c1;
c1 = new coordinate();
c1.x = 6.12;
c1.y = 4.2;

•
Uklanjanje reference
c1 = null;
•
6.12 4.2
6.12 4.2
c1
•
c2
•
2.3 7.6
coordinate c1= new coordinate( );
coordinate c2;
c1.x = 2.3; c1.y = 7.6;
c2 = c1;
Console.WriteLine(c1.x + " , " + c1.y);
Console.WriteLine(c2.x + " , " + c2.y);

Poređenje Value tipova
◦ Operatori “==“ i “!=“ porede vrijednosti

Poređenje Reference tipova
◦ Operatori “==“ i “!=“ porede reference, ne porede
vrijednosti
•
1.0 2.0
Dvije različite reference na iste vrijednosti
•
1.0 2.0
//Vektor je klasa koja posjeduje javni atribut Vrijednost
Vektor x, y;
x = new Vektor();
x.Vrijednost = 30;
y = x;
Console.WriteLine(y.Vrijednost);
y. Vrijednost = 50;
Console.WriteLine(x. Vrijednost);

Koje vrijednosti se ispisuju?



Način poređenja zavisi od tipa objekta,
odnosno da li je Value ili Reference tipa
Kod varijabli koje su Value tipa (prosti tipovi,
instance struktura ili nabrojanja) porede se
vrijednosti
Kod varijabli koje su Reference tipa (klasni
tipovi, instance klasa) porede se reference,
odnosno adrese memorijskih lokacija

System.Object, nekoliko metoda poređenja
◦ ReferenceEquals()
 Ispituje da li su dvije reference iste, tj da li pokazuju
na istu instancu objekta u memoriji
 Nema smisla da se koristi za Value tipove
◦ Equals()
 Poredi reference za Reference tipove, može se
predefinisati za korisničke klase
 Poredi vrijednosti za Value tipove
◦ Operator poređenja (==)
 Za Reference tipove poredi reference, može se
predefinisati
 Za Value tipove poredi vrijednosti, potrebno ga je
redefinisati za korisničke tipove (strukture)

Preklapanje operatora (operator overloading)
◦ predstavlja redefinisanje postojećih operatora zbog
potrebe da na specifičan način rade sa novim
tipovima podataka (npr. klasnim tipovima)
◦ omogućava da se ugrađeni operatori prilagode tako
da izvršavaju određenu akciju nad objektima
klasnih tipova



Moguće je izvršiti preklapanje skoro svih
operatora
Preklapanje operatora treba pažljivo
koristiti, zbog mogućih neželjenih efekata
Primjeri korištenja preklapanja operatora
kod ugrađenih tipova
◦ operator dodjele se koristi na isti način za
različite tipove podataka
◦ operator sabiranja se koristi i za cijele i za realne
brojeve



Za korištenje operatora nad objektima
klasnih tipova u opštem slučaju potrebno je
preklapanje operatora
Preklapanje se vrši tako što se definiše
operatorska funkcija
Operatorske funkcije se implementiraju:
◦ kao metode
◦ kao globalne funkcije, obično prijateljske funkcije
klasa (C++)






Pretpostavimo da su u programu potrebni
kompleksni brojevi i operacije nad njima.
Tip kompleksnog broja će realizovati klasa koja
sadrži elemente (real, imag), a takođe i funkcije za
operacije.
Pogodno je da se pozivi funkcija koje realizuju
operacije mogu notacijski predstaviti standardnim
operatorima.
U jezicima C#/C++, operatori za korisničke tipove
(klase) su specijalne operatorske funkcije.
Operatorske funkcije nose ime operator@, gde je @
neki operator ugrađen u jezik.
Operatorske funkcije preklapaju standaradne
operatore (+, -, *, /, ...).


Operatorske funkcije se mogu koristiti u
izrazima kao i operatori nad ugrađenim
tipovima.
Ako je operatorska funkcija definisana na
prethodno opisan način, izraz [email protected] se
tumači kao operator@(t1,t2):
class complex {
public:
complex(double,double);
friend complex operator+(complex,complex);
friend complex operator-(complex,complex);
private:
double real, imag;
};
/* konstruktor */
/* oparator + */
/* operator - */
complex::complex (double r, double i) : real(r), imag(i) {}
complex operator+ (complex c1, complex c2) {
complex temp(0,0);
// privremena promenljiva tipa complex
temp.real=c1.real+c2.real;
temp.imag=c1.imag+c2.imag;
return temp;
}
complex operator- (complex c1, complex c2) {
return complex(c1.real-c2.real,c1.imag-c2.imag); //poziv konstruktora
}
struct Vector
{
public double x, y, z;
public Vector(Vector rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
public static Vector operator + (Vector lhs, Vector rhs)
{
Vector result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
}
}


C#/C++ dozvoljava preklapanje operatora
kao što dozvoljava i preklapanje imena
funkcija.
Princip preklapanja omogućava da se definišu
nova značenja operatora za korisničke tipove.

Postoje neka ograničenja u preklapanju
operatora:
◦ ne mogu direktno da se preklope svi operatori,
neki ne mogu nikako;
◦ ne mogu da se redefinišu značenja operatora za
primitivne (standardne) tipove podataka;
◦ ne mogu da se uvode novi simboli za operatore;
◦ ne mogu da se mijenjaju osobine operatora koje
su ugrađene u jezik: n-arnost, prioritet i
asocijativnost.

Ako je @ neki binarni operator (npr +), on
može da se realizuje:
◦ Kao funkcija članica klase X
◦ Kao prijateljska globalna funkcija

Nije dozvoljeno da se u programu nalaze obje
ove funkcije
<tip> operator@ (X)
Poziv [email protected] se sada tumači kao:
a.operator@(b) , za funkciju članicu
<tip> operator@ (X,X)
Poziv [email protected] se sada tumači kao:
operator@(a,b) , za globalnu funkciju
class complex {
double real,imag;
public:
complex (double r=0, double i=0) : real(r), imag(i) {}
complex operator+(complex c) { return complex(real+c.real,imag+c.imag; }
};
// ili, alternativno:
class complex {
double real,imag;
public:
complex (double r=0, double i=0) : real(r), imag(i) {}
friend complex operator+(complex,complex);
};
complex operator+ (complex c1, complex c2) {
return complex(c1.real+c2.real,c1.imag+c2.imag);
}
void main () {
complex c1(2,3),c2(3.4);
complex c3=c1+c2; // poziva se c1.operator+(c2) ili operator+(c1,c2)
}

Unarni operator ima samo jedan operand,
pa se može realizovati:
◦ kao operatorska funkcija članica bez argumenata:
tip operator@ ()
◦ kao globalna funkcija sa jednim argumentom:
tip operator@ (X x)

Binarni operator ima dva argumenta, pa se
može realizovati:
◦ kao funkcija članica sa jednim argumentom:
tip operator@ (X xdesni)
◦ kao globalna funkcija sa dva argumenta:
tip operator@ (X xlevi, X xdesni)

Unarni operator može biti preklopljen kao:
◦ nestatička funkcija članica bez argumenata; ne
može biti statička jer mora pristupati pojedinačnom
atributu
◦ samostalna funkcija (nije funkcija članica) sa jednim
argumentom (objekat ili referenca)

Binarni operator može biti preklopljen kao:
◦ nestatička funkcija članica sa jednim argumentom
◦ samostalna funkcija sa dva argumenta (bar jedan
mora biti objekat ili referenca na objekat)
class complex {
//...
public:
complex operator!();
friend complex operator~(complex);
complex operator-(complex);
friend complex operator+(complex,complex);
};
//
//
//
//
članica unarni operator!
globalna f-ja, unarni operator~
članica binarni operatorglobalna f-ja, binarni operator+


Operatorske funkcije realizuju se kao funkcije
članice klasa
Operatorske funkcije se definišu kao javne i
statičke metode klasa
◦ Ne mogu koristiti pokazivač this na objekat date
klase
◦ Imaju jedan argument za unarne, dva za binarne
operatore
◦ Najmanje jedan argument mora biti korisnički
definisan tip (klasa, struktura)
public static Vector operator + (Vector lhs, Vector rhs)
{
Vector result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
}
public static Vector operator * (double lhs, Vector rhs)
{
return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
}
public static double operator * (Vector lhs, Vector rhs)
{
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
}

Postoji 6 relacionih operatora u jeziku C# i
moraju se preklapati u parovima
◦ == i !=
◦ >i<
◦ >= i <=



Ako se izvrši preklapanje operatora ==, mora
se preklopiti i operator !=, u protivnom
kompajler prijavljuje grešku
Slično važi za ostale relacione operatore
Relacioni operatori vraćaju logičku vrijednost



Ako se izvrši preklapanje operatora == i !=,
moraju se predefinisati i funkcije Equals() i
GetHashCode() naslijeđene iz System.Object
Funkcija Equals() treba da implementira istu
logiku kao i operator jednakosti
Ako se ne izvršti redefinisanje prethodne
dvije metode, kompajler generiše upozorenje
(ne grešku)
public static bool operator == (Vector lhs, Vector rhs)
{
if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z)
return true;
else
return false;
}
public static bool operator != (Vector lhs, Vector rhs)
{
return ! (lhs == rhs);
}

Implicitna konverzija
◦ Izvršava se automatski između kompatibilnih tipova
upotrijebljenih u izrazima

Eksplicitna konverzija
◦ Kada postoji rizik gubitka podataka ili pojave
greške u konverziji
◦ Mora se eksplicitno navesti u izrazu
◦ Cast operator (tip) se koristi za eksplicitnu
konverziju tipova
◦ Sintaksa: (tip)varijabla
int i = 3;
long j = i; // implicitna
short s = (short)i; // eksplicitna




Konverzija se definiše kao operatorska
funkcija u okviru klase
Može se definisati kao implicitna ili
eksplicitna konverzija
Uvijek definisati kao eksplicitnu konverziju u
slučaju da postoji bilo kakva mogućnost
greške pri konverziji
Povratni tip operatorske funkcije jednak je
operatoru konverzije
public static implicit operator float (Currency value)
{
return value.Dollars + (value.Cents/100.0f);
}
//primjer definisanja operatora konverzije za slučaj struktura
//na isti način se radi sa klasama
struct Currency
{
public uint Dollars;
public ushort Cents;
public static implicit operator float (Currency value)
{
return value.Dollars + (value.Cents/100.0f);
}
}
...
Currency balance = new Currency(10,50);
float f = balance; //implicitna konverzija Currency u float
struct Currency
{
public uint Dollars;
public ushort Cents;
}
public static explicit operator Currency (float value)
{
uint dollars = (uint)value;
ushort cents = (ushort)((value-dollars)*100);
return new Currency(dollars, cents);
}
}
....
float amount = 45.63f;
Currency amount2 = (Currency)amount; //eksplicitna konverzija
Currency amount3 = amount; // greška


Moguće je definisati konverzije između bilo
koja dva korisnički definisana tipa (klase,
strukture)
Ograničenja
◦ Ne može se definisati konverzija za dvije klase ako
je jedna izvedena iz druge klase
◦ Konverzija se mora definisati u okviru definicije
izvorišne ili odredišne klase (tipa)



Moguće je definisati
konverziju samo između
klasa C i D
Operatorska funkcija za
konverziju se definiše u
okviru definicije klase C
ili D, ne u obje
Mora biti moguć pristup
source kodu klasa C ili D
da bi se realizovala
konverzija
Ograničenja
Hijerarhija klasa
public static explicit operator D(C value)
{
//implementacija konverzije
}
public static explicit operator C(D value)
{
//implementacija konverzije
}

similar documents