Wyklad progr obiekt cz II


Programowanie obiektowe
Cz. II
27 III 2015
Klasa, składowe, interfejs, ...
Wszystko jest obiektem. Obiekt może składać
się innych obiektów  tworząc bardziej złożony
obiekt.
27 III 2015 2
Wykorzystanie obiektów

Pojęcie klasy, składowych oraz interfejsu w obiektowym
paradygmacie programowania

Cykl życia obiektów, konstruktory i destruktory

Polimorfizm kodu poprzez użycie mechanizmów
przeciążania i dziedziczenia

Podsumowanie wykładów, omówienie rezultatów
nauczania, zaliczenia
27 III 2015 3
Klasa

Klasa jest odmianą struktury

Definicja klasy tworzy nowy typ
class worek {
private:
sekcja prywatna
&
protected:
sekcja zabezpieczona
&
public:
sekcja publiczna
&
};
Hermetyzacja danych i metod:
Wewnętrzna struktura obiektu powinna zawsze być ukryta przed swobodnym dostępem.
27 III 2015 4
Klasa

Klasa jest odmianą struktury

Definicja klasy tworzy nowy typ
class worek {
sekcja prywatna:
private:
komponenty w tej sekcji są dostępne tylko w funkcjach swojej klasy
&
protected:oraz w funkcjach zaprzyjaznionych z tą klasą (atrybut friend)
&
sekcja zabezpieczona
public:
&
sekcja publiczna
};
27 III 2015 5
Klasa

Klasa jest odmianą struktury

Definicja klasy tworzy nowy typ
sekcja prywatna:
class worek {
komponenty w tej sekcji są dostępne tylko w funkcjach swojej klasy oraz w funkcjach
private:
zaprzyjaznionych z tą klasą (atrybut friend)
&
protected:sekcja zabezpieczona:
&
komponenty zabezpieczone mogą być dostępne w klasach
public:
pochodnych (prywatne nie mogą)
&
};
sekcja publiczna
27 III 2015 6
Klasa

Klasa jest odmianą struktury

Definicja klasy tworzy nowy typ
sekcja prywatna:
class worek {
komponenty w tej sekcji są dostępne tylko w funkcjach swojej klasy oraz w funkcjach
private:
zaprzyjaznionych z tą klasą (atrybut friend)
&
protected:sekcja zabezpieczona:
komponenty zabezpieczone mogą być dostępne w klasach pochodnych (prywatne nie
&
mogą)
public:
&
sekcja publiczna:
};
Komponenty w sekcji publicznej są dostępne wszędzie.
27 III 2015 7
Klasa
class worek {
private:
static int Rozm;
public:
static int rozmiar(){return Rozm;}
static int rozmiar(int n){
Rozm=n;
return Rozm;
}
};
Pola statyczne:
Są deklarowane atrybutem static.

pola wspólne wszystkim obiektom danej klasy

zajmuje tylko jedno miejsce w pamięci niezależni od ilości obiektów tej klasy
Funkcje statyczne:

nie są wywoływane na rzecz obiektów klasy -więc nie mają zmiennej this i nie mogą się odwoływać
do niestatycznych komponentów klasy

wywołuje się na rzecz klasy reprezentowanej przez swoją nawę, obiekt lub wskaznik (np..
klasa::fun(); klasa.fun(); klasa->fun(); )
27 III 2015 8
Klasa
class worek {
private:
static int Rozm;
public:
static int rozmiar(){return Rozm;}
static int rozmiar(int n){
Rozm=n;
return Rozm;
}
};
int worek::Rozm=10;
main()
{
int n=worek::rozmiar();
worek x;
10
cout << x.rozmiar();
50
cout << x.rozmiar(50);
50
cout << x.rozmiar();
}
27 III 2015 9
Klasa
Pola statyczne służą do przechowywania
class worek {
private:
wspólnych danych dla wszystkich
static int Rozm;
obiektów danej klasy.
public:
Są one zmiennymi globalnymi  ale tylko
static int rozmiar(){return Rozm;}
static int rozmiar(int n){
dla obiektów danej klasy lub klas
Rozm=n;
zaprzyjaznionych.
return Rozm;
}
Muszą być zdefiniowane przed użyciem
};
obiektów danej klasy.
int worek::Rozm=10;
main()
Np. mają kilka klas zaprzyjaznionych z
{
"worek", wszystkie obiekty ("worki") będą
int n=worek::rozmiar();
worek x;
miały cechy wspólne  w tym wypadku
cout << x.rozmiar();
rozmiar (Rozm) więc jest to cecha
cout << x.rozmiar(50);
wspólna dla wszystkich tego typu
cout << x.rozmiar();
obiektów. }
27 III 2015 10
Klasa  wzorce klas
Gdy zachodzi potrzeba definicji kilku podobnych klas, które różnią się np. tylko typem
danych  stosuje się wzorce klas.
Wzorce klas definiuje się słowem kluczowym template oraz listą parametrów w < >.
template class TAB {
static int w; //szerokosc
int tmp,N; //rozmiar
Typ *A; //wskaznik tablicy
public:
TAB():tmp(0),N(0),A(0) {} //konstr.bezagr.
TAB(Typ s):tmp(0),N(1),A(new Typ) {*A=s;) //konwer. z Typ TAB
TAB(Typ[],int); //konstrukcja z tablicy
TAB(TAB&); //konstruktor kopiujący
~TAB();
TAB &operator=(TAB&);
friend ostream &operator<<(ostream&,TAB&);
};
template TAB::TAB(Typ a[], int N):tmp(0),N(N),A(new Typ[N])
{
if (A)
for (int i=0; iA[i]=a[i];
}
27 III 2015 11
Klasa  wzorce klas
template class TAB {
static int w; //szerokosc
int tmp,N; //rozmiar
Typ *A; //wskaznik tablicy
public:
TAB():tmp(0),N(0),A(0) {} //konstr.bezagr.
TAB(Typ s):tmp(0),N(1),A(new Typ) {*A=s;) //konwer. z Typ TAB
TAB(Typ[],int); //konstrukcja z tablicy
TAB(TAB&); //konstruktor kopiujący
~TAB();
TAB &operator=(TAB&);
friend ostream &operator<<(ostream&,TAB&);
};
template TAB::TAB(Typ a[], int N):tmp(0),N(N),A(new Typ[N]){
if (A) for (int i=0; itemplate TAB::TAB( &S):tmp(0),N(S.N),A(S.A?new Typ[N]:0) {
if (A) for (int i=0; i if (S.tmp) delete &S;}
template TAB::~TAB() {
if (A) delete A; A=0; }
template TAB &TAB::operator=(TAB &S) {
if (this==&S) return *this;
if (A) delete A;
N=S.N;
A=S.A?new Type[N]:0;
if (A) for (int i=0; i if(S.tmp) delete &S;
27 III 2015 12
return *this;
}
Klasa  wzorce klas
template class TAB {
static int w; //szerokosc
int tmp,N; //rozmiar
Typ *A; //wskaznik tablicy
public:
TAB():tmp(0),N(0),A(0) {} //konstr.bezagr.
TAB(Typ s):tmp(0),N(1),A(new Typ) {*A=s;) //konwer. z Typ TAB
TAB(Typ[],int); //konstrukcja z tablicy
TAB(TAB&); //konstruktor kopiujący
~TAB();
TAB &operator=(TAB&);
friend ostream &operator<<(ostream&,TAB&);
};
template TAB::TAB(Typ a[], int N):tmp(0),N(N),A(new Typ[N]){
if (A) for (int i=0; itemplate TAB::TAB( &S):tmp(0),N(S.N),A(S.A?new Typ[N]:0) {
if (A) for (int i=0; i if (S.tmp) delete &S;}
template TAB::~TAB() {
if (A) delete A; A=0; }
template TAB &TAB::operator=(TAB &S) {
if (this==&S) return *this;
if (A) delete A;
N=S.N;
A=S.A?new Type[N]:0;
if (A) for (int i=0; i if(S.tmp) delete &S;
return *this;}
template ostream &operator << (ostream &wy, TAB &S) {
for (int i=0; i if (S.tmp) delete &S;
return wy;}
27 III 2015 13
Klasa  wzorce klas
int TAB::w=4; //TAB
int a[]={1,2,3,4,5,6,7,8,9,10};
int TAB::w=1; //TAB
char *t="Tekst jakis";
int TAB::w=3; //TAB
ZESP b[]={ZESP(1,2), ZESP(3.4,1.9), ZESP(0,0)};
void main()
{
TAB X(a,sizeof(a)/sizeof(a[0]));
TAB Y(t,strlen(t));
TAB Z(b,sizeof(b)/sizeof(b[0]));
cout << "X="<}
27 III 2015 14
Klasa  this
Słowo kluczowe this jest wskaznikiem do obiektu na rzecz którego jest wykonana
dana metoda.
class ABC{
public:
void pokaz_adres(ABC *obiekt)
{
cout << "Moj adres="<< this <<" adres parametru="<< obiekt< }
};
int main()
{
ABC a,b;
a.pokaz_adres(&a);
b.pokaz_adres(&b);
a.pokaz_adres(&b);
b.pokaz_adres(&a);
return 0;
}
27 III 2015 15
Klasa  this
Słowo kluczowe this jest wskaznikiem do obiektu na rzecz którego jest wykonana
dana metoda.
1. Odróżnienie zmiennych metody (funkcji) od jej parametrów:
class wspolrzedne {
private:
double x,y;
public:
void wprowadz(double x, double y)
{
this->x=x;
this->y=y;
}
}
int main()
{
wspolrzedne A;
A.wprowadz(1,2);
}
27 III 2015 16
Klasa  this
class Oferta{
private:
string adres;
int cena;
public:
Oferta (string adres="WWW", int cena=100)
{ this->adres=adres;
this->cena=cena;}
void pokaz()
{ cout << "adres="<< adres<<" cena="< Oferta& operator= (const Oferta &x)
Słowo kluczowe this jest wskaznikiem do
{ adres=x.adres;
obiektu na rzecz którego jest wykonana
cena=x.cena;
return *this; }
dana metoda.
};
2. Zwrócenie referencji jako wartość funkcji
int main()
{
lub parametr
Oferta c,d("aaa",200);
c.pokaz();
d.pokaz();
c=d;
c.pokaz();
return 0;
}
27 III 2015 17
Wykorzystanie obiektów

Pojęcia klasy, składowych oraz interfejsu w obiektowym
paradygmacie programowania

Cykl życia obiektów, konstruktory i destruktory

Polimorfizm kodu poprzez użycie mechanizmów
przeciążania i dziedziczenia

Podsumowanie wykładów, omówienie rezultatów
nauczania, zaliczenia
27 III 2015 18
Konstruktory
Konstruktor  jest to funkcja o nazwie klasy, bez typu (bez void) nie zwracająca wartości.
Jeśli nie został zdefiniowany żaden konstruktor, to niejawnie jest definiowany konstruktor
bezparametrowy Klasa() i konstruktor kopiujący Klasa(Klasa&).
Jest on niejawnie wykonywany przy tworzeniu obiektu. Jego zadanie to zorganizowanie
tworzonego obiektu. Domyślny konstruktor rezerwuje tylko pamięć. Czasem zachodzi
potrzeba inicjalizacji zmiennych obiektu czy alokacji pamięci.
class ZESP{
private:
double Re, Im;
public:
ZESP (double re, double im)
{ Re=re; Im=im;}
}
Tworząc obiekt typu ZESP można dzięki konstruktorowi nadać wartości początkowo polu
Re oraz Im;
27 III 2015 19
Konstruktory
class tekst{
private:
int len,tmp;
char *txt;
//...
public:
tekst (char *t)
{
len=strlen(t);
tmp=0;
txt=new char[len+1];
strcpy(txt,t);
}
}
//
tekst a("ala ma kota");
Konstruktor klasy tekst zaalokuje bufor na tekst i przepisze tekst do tego bufora.
27 III 2015 20
Konstruktory
Konstruktor bezparametrowy  ma za zadanie stworzyć obiekt bez inicjacji
wartościami.
Jeśli zdefiniowano inny konstruktor to kompilator nie dołączy własnej definicji konstruktora
domyślnego.
class Klasa{
//..
public:
Klasa() {};
}
class ZESP{
private:
double Re, Im;
public:
ZESP() {Re=0; Im=0;}
}
tekst() {tmp=0; len=0; txt=NULL;}
27 III 2015 21
Konstruktory
Konstruktor kopiujący  ma za zadanie stworzyć obiekt i zainicjować go inny obiektem
tej samej klasy.
class Klasa{
//..
public:
Klasa(Klasa &); //nagłówek
}
Jest aktywowany:

gdy definiowany obiekt jest inicjowany innym obiektem tej samej klasy

podczas przekazywania obiektów przez wartość (jeśli argument funkcji jest
przekazywany przez wartość (nie * lub &) to wewnątrz funkcji tworzony jest lokalny
obiekt za pomocą konstruktora kopiującego).
27 III 2015 22
Konstruktory
ZESP X,Y;
tekst t;
ZESP A(X), B=X, *wsk=new ZESP(X), C[]={X,Y};
tekst u(t), v=t;
Jeśli konstruktor kopiujący nie został zdefiniowany, to kompilator niejawnie dołącza
własną jego definicję.
Domyślny konstruktor kopiujący kopiuje do nowego obiektu pole po polu.
ZESP (ZESP &z) {Re=z.Re; Im=z.Im;}
tekst (tekst(&s)){
tmp=0;
if (s.txt) {
len=s.len;
txt= new char [len+1];
strcpy(txt,s.txt);
}
else {txt=NULL; len=0;}
if (s.tmp) delete &s; //usuń obiekt tymczasowy
}
27 III 2015 23
Konstruktory
Konwersja konstruktorowa
klasa (typ);
Służy do konwersji typów. W tym wypadku z typu "typ" do typu "klasa".
ZESP (double re) {Re=re; Im=0};
tekst (char *t){
tmp=0;
if (t) {
len=strlen(t);
txt=new char [len+1];
strcpy(txt, t);
}
else {txt=NULL; len=0;}
}
W pewnym momencie, gdy zajdzie konieczność wykorzystania typu "klasa" a nie "typ" to
obiekt tej klasy jest automatycznie tworzony przy pomocy konwersji konstruktorowej.
Klasa + typ drugi argument (typ) zostanie poddany także konwersji do typu Klasa.
27 III 2015 24
Konstruktory
Konwersja konstruktorowa
klasa (typ);
ZESP A=1, B(3), *wsk=new ZESP(2);
B=A+22;
B=ZESP(3.1415);
tekst t1="Ala ", t2("ma ");
t1+="kota ";
B=A+22 najpierw A, ZESP(22), potem B=A+ZESP(22)
lub B=A.operator+(ZESP(22));
Liczba 22 musi być przekonwertowana do typu ZESP, bo wymaga tego operator+.
27 III 2015 25
Konstruktory
Konstruktory wieloargumentowe, lista inicjacyjna
Można definiować konstruktory wielo-argumentowe.
ZESP A(1,-1); *wsk=new ZESP(1,1);
A=ZESP(2,2);
Jednym z zadań konstruktorów jest nadawanie wartości polom klasy, itd. Funkcja
konstruktora jest wykonana po utworzeniu obiektu.
ZESP::ZESP(double re, double im)
{ Re=re; Im=im }
ZESP::ZESP(double Re, double Im) ZESP::ZESP(double Re, double Im)
{ Re=Re; Im=Im } { ZESP::Re=Re; ZESP::Im=Im }
przesłanianie parametrów
27 III 2015 26
Konstruktory
Konstruktory wieloargumentowe, lista inicjacyjna
Polom klasy można nadać wartości podczas tworzenia obiektu za pomocą listy
inicjacyjnej. Są to nazwy pól (niestatyczne) po : oddzielone , z wyrażeniami ujętymi w ( )
klasa::naglowek_konstr:lista_inicjacyjna { konstruktor }
pole1(wyr1),pole2(wyr2), ...
ZESP::ZESP(double re, double im):Re(re), Im(im) { }
w liście inicjacyjnej jest jawnie podane co jest polem a co wyrażeniem (parametrem) to
nie ma ryzyka przysłaniania parametrów:
ZESP::ZESP(double Re, double Im):Re(Re), Im(Rm) { }
ZESP::ZESP(double Re, double Im)
{ Re=Re; Im=Im }
27 III 2015 27
Konstruktory
Konstruktory wieloargumentowe, lista inicjacyjna
Polom klasy można nadać wartości podczas tworzenia obiektu za pomocą listy
inicjacyjnej. Są to nazwy pól (niestatyczne) po : oddzielone , z wyrażeniami ujętymi w ( )
klasa::naglowek_konstr:lista_inicjacyjna { konstruktor }
pole1(wyr1),pole2(wyr2), ...
tekst(char *t, int tmp): tmp(tmp), len(t?strlen(t):0)
{ if (t) {
txt=new char [len+1];
strcpy(txt,t);
}
else txt=NULL;
}
Pola które są referencjami lub obiektami można nadać wartości jedynie przez listę
inicjacyjną.
Jeśli pole obiektowe nie jest inicjowane w liście inicjacyjnej to wykonywany jest
konstruktor bezparametrowy.
27 III 2015 28
Konstruktory
Destruktor
jest to bezargumentowa funkcja o tej samej nazwie co KLASA ze znakiem~.
~KLASA()
Jest wywoływany niejawnie gdy usuwany jest obiekt danej klasy.
Wywołanie destruktora na rzecz obiektu nie usuwa go a jedynie wywołuje funkcję
destruktora.
Jeśli w obiekcie są zaalokowane bufory to domyślny destruktor ich nie usuwa i będą one
ciągle w pamięci. Bufory takie muszą być usuwane przez odpowiednio zdefiniowany
destruktor.
tekst::~tekst()
{
if (txt) delete txt;
txt=NULL;
}
Destruktor wykonywany jest przed usunięciem obiektu.
27 III 2015 29
Konstruktory
class tekst {
private:
int len,tmp;
char *txt;
public:
konstruktor bezpar.
tekst();
tekst(tekst &);
konstruktor kopiujący
tekst(char *);
konstruktor konwersji z typu char *
~tekst();
destruktor
tekst &operator=(const tekst&);
const tekst &operator+(const tekst&);
tekst &operator+=(tekst &);
friend const tekst &operator+(char *, tekst &);
friend ostream &oerator<<(ostream&,const tekst&);
};
tekst::tekst(): len(0),temp(0),txt(NULL){}
tekst::tekst(tekst &s):len(s.len),tmp(0){
if (s.txt){
txt=new char [len+1];
if (txt) strcpy(txt,s.txt);
else len=0;
}
else txt=NULL;
if (s.tmp) delete &s;
}
27 III 2015 30
Konstruktory
tekst::~tekst(){
if (txt) delete txt;
txt=NULL;
}
tekst& tekst::operator=(const tekst &s){
if (&s==this) return this; //tożsame przypisanie T=T;
delete txt;
len=s.len;
if (s.txt){
txt=new char [len+1];
if (txt) strcpy(txt,s.txt);
else len=0;
}
else txt=NULL;
if (s.tmp) delete &s;
return *this;
}
tekst::tekst(char *t):len(t?strlen(t):0),tmp(0){ //konstr.konw.z char*
if(t){
txt=new char [len+1];
if (txt) strcpy(txt,t);else len=0;
}
else txt=NULL;
}
27 III 2015 31
Konstruktory
W przypadku klasy "tekst":
tekst T,A,B;
i jeśli mamy instrukcje T=A+B, to prawym argumentem operatora przypisania (=) jest
wynik (A+B). Wynik ten jest zapamiętany z obiekcie tymczasowym, który po wykonaniu
operacji powinien być usunięty.
Konieczne jest usuwanie buforów.
27 III 2015 32
Wykorzystanie obiektów

Pojęcia klasy, składowych oraz interfejsu w obiektowym
paradygmacie programowania

Cykl życia obiektów, konstruktory i destruktory

Polimorfizm kodu poprzez użycie mechanizmów
przeciążania i dziedziczenia

Podsumowanie wykładów, omówienie rezultatów
nauczania, zaliczenia
27 III 2015 33
Polimorfizm, dziedziczenie, przeciążenie ...
Pojęcia polimorfizmu, dziedziczenia oraz przeciążenia są
związane (głównie) z metodami klasy (funkcjami).

Funkcje składowe i zaprzyjaznione

Funkcje operatorowe

Operatory specjalne

Konwertery typów

Dziedziczenie

Funkcje polimorficzne
27 III 2015 34
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje stałe:
Deklaruje i definiuje się kończąc nagłówek funkcji słowem const.
void funkcja() const;
void klasa::funkcja() const
{
// ...
}
Funkcje stałe nie mogą modyfikować obiektu, na rzecz którego są
aktywowane. Np.:
class wektor{
int x,y;
& }
Niedozwolona modyfikacja. Przypisanie
int wektor::zeruj() const
x=0 modyfikuje pole x obiektu na rzecz
{ x=0;
którego wywoływana jest stała funkcja
return y;
}
zeruj  a stała funkcja tego robić nie
może.
27 III 2015 35
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje stałe:
Na rzecz obiektów stałych można aktywować tylko funkcje stałe.
Funkcje mogą zwracać obiekty stałe:
const klasa funkcja();
Funkcje stałe to nie to samo co funkcje zwracające obiekty stałe.
Funkcja stałą deklaruje i definiuje się z const na początku i na końcu.
const klasa funkcja() const;
27 III 2015 36
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje zaprzyjaznione:
mogą odwoływać się do prywatnych
(private, protected, public)
komponentów klasy.
class PKP{
friend int oblicz(trasa x,y);
};
Nie są w zakresie klasy  więc nie
mogą być prywatne ani
int oblicz(trasa x,y)
{
zabezpieczone.
return x+y;
}
Zaprzyjaznia się z klasą
umieszczając w jej definicji
deklarację tej funkcji z atrybutem
friend. Definicja nie ma już tego
atrybutu.
27 III 2015 37
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje zaprzyjaznione:
mogą być zaprzyjaznione z wieloma klasami i wtedy jej definicja musi
wystąpić po definicji wszystkich tych klas.
class PKP;
class Oferta{
friend void PKP::pokaz(Oferta&);
};
class PKP{
trasa x,y;
void pokaz(Oferta &X)
{
cout << X.adres << " z " << x << "do"< cout << X.cena;
}
};
27 III 2015 38
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje zaprzyjaznione:
można zaprzyjaznić wszystkie funkcje (metody) innej klasy. Ich definicje
muszą nastąpić po definicjach rozpatrywanych klas.
class PKP;
class Oferta{
friend class PKP;
};
class PKP{
trasa x,y;
void pokaz(Oferta &X)
{
cout << X.adres << " z " << x << "do"< cout << X.cena;
}
};
27 III 2015 39
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje operatorowe:
Obiekty są "normalnymi" zmiennymi o określonym typie, więc można na
nich wykonywać działania  np. matematyczne.
int x,y;
x=10;
y=20;
x=y+10;
Samochody A,B,C;
C=A+B;
Z tą różnicą- że należy zdefiniować operatory, by sprecyzować w jaki
sposób mają one (operatory) wpływać na obiekty (np. A i B).
27 III 2015 40
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje operatorowe:
Słowo kluczowe operator, po którym podaje się symbol operatora- np..
operator+, operator(), operator++,...
Nie można zmienić liczby argumentów operatora.
Nie można zmienić priorytetów.
Nie można przeciążać operatorów . .* :: ?: # ##
Funkcje operatorowe są funkcjami, z rozróżnieniem na argument lew i
prawy.
Jeżeli funkcja operatorowa jest funkcją danej klasy to obiekt na rzecz
którego jest wywoływana stanowi lewy argument definiowanego operatora
dwuargumentowego (lub jedyny jednoargumentowego),
27 III 2015 41
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje operatorowe:
Jeśli funkcja operatora jest tylko zaprzyjazniona z daną klasą to jej
pierwszy argument jest lewym argumentem operatora.
typ klasa::operator+()
typ klasa::operator+(typ arg_prawy)
-funkcje zaprzyjaznione z klasą
typ operator+(Klasa arg_lewy)
typ operator+(typ arg_lewy,typ arg_prawy)
27 III 2015 42
Polimorfizm, dziedziczenie, przeciążenie ...
Funkcje operatorowe:
Jeśli funkcja operatora jest tylko zaprzyjazniona z daną klasą to jej
pierwszy argument jest lewym argumentem operatora.
class Wekt{
int x,y;
public:
Wekt(int x=0, int y=0)
{ this->x=x;this->y=y;}
Wekt operator+(Wekt a)
{return Wekt(this->x+a.x, this->y+a.y);}
friend ostream &operator<<(ostream &c, Wekt &d)
{return c<< "("<< d.x << "," << d.y <<")";}
};
int main()
w3=w1.operator +(w2);
{
Wekt w1(1,2),w2(3,4),w3,w4;
cout << w1 << "+" << w2 << endl;
w3=w1+w2;
cout << w3 << endl;
}
27 III 2015 43
Polimorfizm, dziedziczenie, przeciążenie ...
Lepiej jest robić to przez referencję  minimalizacja ilości tworzenia
tymczasowych obiektów
class Wekt{
int x,y;
public:
Wekt(int x=0, int y=0)
{ this->x=x;this->y=y;}
const Wekt& operator+(Wekt &a)
{return Wekt(this->x+a.x, this->y+a.y);}
...
Z uwagi na uniknięcie błędnego wykorzystania operatora (co może
sprowadzić się do błędów kompilacji) należy zdefiniować funkcję
operatorową jako const. Np. w przypadku złożonych operacji A+B=C,
gdzie lewy argument przypisania = nie może być obiekt stały. Więc jeśli
funkcja O+ będzie dawać w wyniku obiekt stały  nie będzie on mógł
wystąpić po lewej stronie operatora przypisania.
27 III 2015 44
Polimorfizm, dziedziczenie, przeciążenie ...
class Wekt{
int x,y;
public:
Wekt(int x=0, int y=0)
{ this->x=x;this->y=y;}
const Wekt& operator+(Wekt &a)
{return Wekt(this->x+a.x, this->y+a.y);}
...
Teraz np. dla D=A+B+C mamy (A+B) + C  więc lewym argumentem +
jest obiekt stały (A+B)  błąd. Niestała funkcja nie może być aktywowana
na rzecz obiektu stałego. Zdefiniujemy ją jako funkcję stałą oraz argument
także jako stały:
public:
Wekt(int x=0, int y=0)
{ this->x=x;this->y=y;}
const Wekt& operator+(const Wekt &a) const
{return Wekt(this->x+a.x, this->y+a.y);}
...
27 III 2015 45
Polimorfizm, dziedziczenie, przeciążenie ...
public:
Wekt(int x=0, int y=0)
{ this->x=x;this->y=y;}
const Wekt& operator+(const Wekt &a) const
{return Wekt(this->x+a.x, this->y+a.y);}
...
Dzięki temu, że funkcja operator+ jest stała, można uczynić
niepoprawność instrukcji typu:
A+B=C czy cin >> (A+B);
27 III 2015 46
Polimorfizm, dziedziczenie, przeciążenie ...
Operatory specjalne to:

operator indeksowania [ ]

operator przypisania =

operator wywołania funkcji ( )

operator wyboru komponentu ->
Mogą być definiowane tylko jako niestatyczne metody klasy- a więc są
aktywowane (zawsze) na rzecz obiektu swojej klasy.
A więc ich lewym argumentem może być tylko obiekt tej klasy
27 III 2015 47
Polimorfizm, dziedziczenie, przeciążenie ...
Operator indeksowania [ ]
Przeciążony  jako lewy argument ma obiekt swojej klasy
globalny  jako lewy argument ma wskaznik.
char &operator[](int n)
{
if (n<0) n=0;
else if (n>=dlugosc) n=dlugosc-1;
return tekst[n];
Auta [x]  lewym jest Auta a prawym x.
}
Jeśli Auta to obiekt klasy, to użyty zostanie przeciążony operator.
Jeśli Auta to tablica  użyty zostanie globalny
np..
Auta[x][y]  oraz Auta to tablica, to opracowane to zostanie jako
(Auta[x])[y] najpierw globalny, potem przeciążony.
27 III 2015 48
Polimorfizm, dziedziczenie, przeciążenie ...
Operator wywołania funkcji ()
Globalny  lewym jest wskaznik do funkcji (nazwa), prawym lista wyrażeń.
Przeciążony- lewy obiekt klasy.
tekst & tekst::operator() (int a, int b)
{
tekst *t=new tekst;
t->tmp=1; //tymczasowy marker
if (a>b) return *t;
if (b<0) b=0;
const & . const
if (b>=dlugosc) b=dlugosc-1;
t->dlugosc=b-a +1;
- by można go aktywować na rzecz
t->txt= new char [t->dlugosc+1];
strncpy (t->txt, txt+b, t->dlugosc); obiektów stałych
t->txt[t->dlugosc]='\0\;
if (tmp) delete this;
return *t;
}
ma
tekst A="Ala ma kota";
cout << a(4,5);
27 III 2015 49
Polimorfizm, dziedziczenie, przeciążenie ...
Operator wyboru komponentu ->
Przeciążony  jednoargumentowy, globalny -dwu.
Przeciążony  ma tylko lewy argument i jest to obiekt klasy. W globalnym
jest to wskaznik na obiekt w zależności od typu argumentu lewego
wywoływany jest odpowiedni operator. Np. deklaracje:
KLASA *operator->();
KLASA &operator->();
KLASA operator->();
np.. gdzie wynikiem jest wskaznik na obiekt,
x-> y
( x.operator->() ) -> y
op. przec. op. globalny
27 III 2015 50
Polimorfizm, dziedziczenie, przeciążenie ...
Operator wyboru komponentu ->
np.. gdzie wynikiem jest inny obiekt
x-> y
( x.operator->() ) -> y
op. przeciążony zwracający inny obiekt  np. Z
Z-> y
( Z.operator->() ) -> y
(op. globalny)
op.przeciążony zwracający wskaznik
27 III 2015 51
Polimorfizm, dziedziczenie, przeciążenie ...
Operator przypisania =
Dwuargumentowy. W przypadku braku definicji  niejawnie dodawana jest
funkcja operatorowa:
KLASA & operator=(const Klasa&);
realizuje ona przypisanie pole-po-polu.
Przypisanie wielokrotne (A=B=C) wymaga zastosowania zwracania
wyniku typu referencja do (&).
27 III 2015 52
Polimorfizm, dziedziczenie, przeciążenie ...
class Wekt{
int x,y;
public:
Wekt(int x=0, int y=0)
{ this->x=x;this->y=y;}
const Wekt operator+(const Wekt a) const
{ return Wekt(x+a.x, y+a.y); }
friend ostream &operator<<(ostream &c, Wekt &d)
{return c<< "("<< d.x << "," << d.y <<")";}
Wekt& operator=(const Wekt &obj)
{ x=obj.x*10;
y=obj.y;
return *this;}
};
int main()
{
Wekt w1(1,2),w2(3,4),w3,w4;
cout << w1 << "+" << w2 << endl;
(1,2)+(3,4)
w3=(w1+w2);
(40,6)
cout << w3 << endl;
(40,6)
w3=w2+w1+w4;
cout << w3 <_
}
27 III 2015 53
Polimorfizm, dziedziczenie, przeciążenie ...
Konwerter  konwersja typu
Są to jednoargumentowe funkcje operatorowe bez argumentów jawnych
oraz bez wyniku. Formułują konwersje z typu klasy do innego typu.
operator typ ();
class Wektor{
...
operator double()
{
return sqrt(x*x + y*y);
}
&
Wektor A(3,4);
25
cout << double(A);
_
27 III 2015 54
Polimorfizm, dziedziczenie, przeciążenie ...
Pojęcia polimorfizmu, dziedziczenia oraz przeciążenia są
związane (głównie) z metodami klasy (funkcjami).

Funkcje składowe i zaprzyjaznione

Funkcje operatorowe

Operatory specjalne

Konwertery typów

Dziedziczenie

Funkcje polimorficzne
27 III 2015 55
Wykorzystanie obiektów

Pojęcia klasy, składowych oraz interfejsu w obiektowym
paradygmacie programowania

Cykl życia obiektów, konstruktory i destruktory

Polimorfizm kodu poprzez użycie mechanizmów
przeciążania i dziedziczenia

Podsumowanie wykładów, omówienie rezultatów
nauczania, zaliczenia
27 III 2015 56


Wyszukiwarka

Podobne podstrony:
Wyklad progr obiekt cz III
Wyklad progr obiekt cz I a
Wykład 9 Kap obr cz II
Psychopatologia UW Wykład III RS cz II dla stud
Konspekt do Wykladu Ramy zelbetowe cz II przegubowe polaczenie slup stopa
Wyklad 8?rmatozy endokrynologiczne cz II
Podstawy edytorstwa wykład cz II
2009 SP Kat prawo cywilne cz II
413 (B2007) Kapitał własny wycena i prezentacja w bilansie cz II
Fotografia ślubna zdjęcia w plenerze, cz II
Choroby obturacyjne górnych dróg oddechowych u koni cz II(1)

więcej podobnych podstron