Zesp

Transkrypt

Zesp
Tematyka wykładów
1.
Wprowadzenie. Klasy – cz. 1
2.
Klasy – cz. 2
3.
4.
5.
6.
7.
8.
Funkcje operatorowe. Wskaźnik this
Dziedziczenie
Polimorfizm i funkcje wirtualne
Szablony
Strumienie
Tworzenie aplikacji w systemie Windows
- Język C++. Programowanie obiektowe
- Klasy i obiekty
- Budowa i deklaracja klasy. Prawa dostępu
- Pola i funkcje składowe
- Konstruktor i destruktor
- Tworzenie obiektów
- Konstruktor kopiujący. Pola tworzone
statycznie i dynamicznie
- Funkcje zaprzyjaźnione
- Składowe statyczne
Przeciążanie operatorów
Przeciążanie (przeładowywanie) operatora pozwala na
zdefiniowanie jego działania dla argumentów typu
obiektowego (tzn. nadanie operatorowi nowego znaczenia).
Cechy przeciążania operatorów:
• standardowe działanie operatora dla danych typów
prostych pozostaje bez zmian
• nie jest możliwa zmiana liczby argumentów operatora
• nie jest możliwa zmiana priorytetu operatora
• nie jest możliwa zmiana wiązania operatora
• nie jest możliwe tworzenie nowych operatorów –
przeciąża się istniejące.
Działanie operatora można zdefiniować w dowolny sposób
(formalnie dopuszczalne jest przeciążenie operatora + tak,
aby np. odejmował obiekty, ale nie należy tak postępować).
Funkcje operatorowe
Przeciążenie operatora polega na zdefiniowaniu funkcji
operatorowej.
Funkcja operatorowa to funkcja o nazwie
operator <symbol_operatora>
Przykłady:
operator+
operator<<
operator()
operator new
Funkcje operatorowe mogą być definiowane jako:
• funkcje składowe klasy
• funkcje zaprzyjaźnione z klasą
Przeciążanie operatorów
Nie jest możliwe przeciążanie operatorów:
.
.*
?:
::
sizeof
Następujące operatory należy przeciążać jako funkcje
składowe:
=
()
[]
->
domyślny operator =
(„pole po polu”)
W przypadku użycia strumieni WE / WY, następujące
operatory należy przeciążać jako funkcje zaprzyjaźnione:
<<
>>
Funkcje operatorowe
class Zesp
{
public:
Zesp();
Zesp(float a, float b);
private:
float re, im;
};
Zesp::Zesp()
{
re = im = 0;
}
Zesp::Zesp(float a, float b)
{
re = a; im = b;
}
Problem: klasę Zesp należy uzupełnić o operacje:
• dodawania liczb zespolonych
operatory 2-argumentowe
• odejmowania liczb zespolonych
• zmiany znaku liczby zespolonej - operator 1-argumentowy
Funkcja operatorowa składowa
(operator 2-argumentowy)
ROZWIĄZANIE 1:
class Zesp
{
public:
Zesp();
Zesp(float a, float b);
Zesp dodaj(Zesp z);
Zesp operator+ (Zesp z);
private:
float re, im;
};
Zesp Zesp::dodaj(Zesp z)
{
return Zesp(re+z.re,
im+z.im);
}
Zesp Zesp::operator+ (Zesp z)
{
return Zesp(re+z.re,
im+z.im);
}
funkcje
składowe klasy
void main()
{
Zesp z1(2, 5), z2(1, -3), z3;
z3 = z1.dodaj(z2);
z3 = z1.operator+ (z2);
z3 = z1+z2;
}
Funkcja operatorowa zaprzyjaźniona
(operator 2-argumentowy)
ROZWIĄZANIE 2:
class Zesp
{
public:
Zesp();
Zesp(float a, float b);
friend Zesp odejmij(Zesp z1, Zesp z2);
friend Zesp operator- (Zesp z1, Zesp z2);
private:
float re, im;
};
funkcje zaprzyjaźnione z klasą
Funkcja operatorowa zaprzyjaźniona
(operator 2-argumentowy)
ROZWIĄZANIE 2:
Zesp odejmij(Zesp z1, Zesp z2)
{
return Zesp(z1.re-z2.re, z1.im-z2.im);
}
Zesp operator– (Zesp z1, Zesp z2)
{
return Zesp(z1.re-z2.re, z1.im-z2.im);
}
void main()
{
Zesp z1(2, 5), z2(1, -3), z3;
z3 = odejmij(z1, z2);
z3 = operator– (z1, z2);
z3 = z1-z2;
}
Funkcja operatorowa składowa
(operator 1-argumentowy)
ROZWIĄZANIE 1:
class Zesp
{
public:
Zesp();
Zesp(float a, float b);
Zesp minus();
Zesp operator- ();
private:
float re, im;
};
Zesp Zesp::minus()
{
return Zesp(-re, -im);
}
Zesp Zesp::operator- ()
{
return Zesp(-re, -im);
}
funkcje składowe klasy
void main()
{
Zesp z1(2, 5), z2;
z2 = z1.minus();
z2 = z1.operator- ();
z2 = -z1;
}
Funkcja operatorowa zaprzyjaźniona
(operator 1-argumentowy)
ROZWIĄZANIE 2:
class Zesp
{
public:
Zesp();
Zesp(float a, float b);
friend Zesp minus(Zesp z);
friend Zesp operator- (Zesp z);
private:
float re, im;
};
funkcje zaprzyjaźnione z klasą
Funkcja operatorowa zaprzyjaźniona
(operator 1-argumentowy)
ROZWIĄZANIE 2:
Zesp minus(Zesp z)
{
return Zesp(-z.re, -z.im);
}
Zesp operator– (Zesp z)
{
return Zesp(-z.re, -z.im);
}
void main()
{
Zesp z1(2, 5), z2;
z2 = minus(z1);
z2 = operator– (z1);
z2 = -z1;
}
Dlaczego konieczne są funkcje
operatorowe zaprzyjaźnione?
MNOŻENIE OBIEKTU PRZEZ WARTOŚĆ
void main()
{
float x = 5;
Zesp z1(2, 5), z2;
z2 = x * z1;
}
Funkcja składowa
z2 = x.operator* (z1);
float
ŹLE!
Funkcja zaprzyjaźniona
z2 = operator* (x, z1);
Funkcja operatorowa zaprzyjaźniona
Zesp operator* (float x, Zesp z)
{
Zesp wynik;
wynik.re = x*z.re;
wynik.im = x*z.im;
return wynik;
}
Dlaczego konieczne są funkcje
operatorowe zaprzyjaźnione?
STRUMIENIE WE / WY
void main()
{
Zesp z1(2, 5), z2;
cout << z1;
cin >> z2;
}
ostream
Funkcje składowe
Funkcje zaprzyjaźnione
cout.operator<< (z1);
operator<< (cout, z1);
cin.operator>> (z2);
operator>> (cin, z2);
istream
ŹLE!
Funkcja operatorowa zaprzyjaźniona
ostream& operator<< (ostream &os, Zesp z)
{
os << ‘(‘ << z.re << ‘,‘ << z.im << ‘)‘;
return os;
}
istream& operator>> (istream &is, Zesp &z)
{
is >> z.re;
is >> z.im;
return is;
}
Wskaźnik this
Wskaźnik this zawiera adres obiektu bieżącego
(tzn. obiektu, na rzecz którego wywołano funkcję składową).
Wskaźnik ten jest dostępny wyłącznie wewnątrz niestatycznych
funkcji składowych.
this
*this
-
adres obiektu
obiekt (wartość obiektu)
Słowo kluczowe this jest stosowane wszędzie tam, gdzie
w funkcji składowej istnieje potrzeba zwrócenia wskaźnika
na obiekt lub wartości obiektu.
return this
return *this
-
adres obiektu
obiekt
Zastosowanie wskaźnika this
Zesp Zesp::operator+= (Zesp z)
{
re += z.re;
// this->re += z.re;
im += z.im;
// (*this).im += z.im;
return *this;
}
zwrócenie obiektu po modyfikacji
void main()
{
Zesp z1(2, 3), z2(3, 5);
z1.operator+= (z2);
z1 += z2;
}
Podsumowanie
Operator dwuargumentowy
Funkcja składowa:
Zesp operator+ (Zesp z);
Funkcja zaprzyjaźniona:
friend Zesp operator- (Zesp z1, Zesp z2);
Operator jednoargumentowy
Funkcja składowa:
Zesp operator- ();
Funkcja zaprzyjaźniona:
friend Zesp operator- (Zesp z);

Podobne dokumenty