Bogdan Kreczmer bogdan.kreczmer@pwr.wroc.pl Zakład Podstaw Cybernetyki i Robotyki Instytut Informatyki, Automatyki i Robotyki Politechnika Wrocławska Kurs: Copyright c 2010 Bogdan Kreczmer Niniejszy dokument zawiera materiały do wykładu dotyczącego programowania obiektowego. Jest on udostępniony pod warunkiem wykorzystania wyłącznie do własnych prywatnych potrzeb i może on być kopiowany wyłącznie w całości, razem z niniejszą stroną tytułową.
Niniejsza prezentacja została wykonana przy użyciu systemu składu L A TEX oraz stylu beamer, którego autorem jest Till Tantau. Strona domowa projektu Beamer: http://latex-beamer.sourceforge.net
1 Struktury danych w języku C++ class, struct, union 2 Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji 3 Hamowanie propagacji błędu 4 Zmienne globalne versus zmienne statyczne
Podstawowe własności class, struct, union W języku C++ istnieją trzy rodzaje definicji struktur złożonych rozpoczynających się od słów kluczowych: class, struct, union. Dwie pierwsze definiują klasę. Jednak nie każda z nich może zawierać wszystkie dostępne własności klasy. Poprzez union definiowana jest struktura specjalna (analogicznie jak w języku C). class NazwaKlasy // Domyślnie prywatna protected: private: public: ; struct NazwaKlasy // Domyślnie publiczna private: protected: public: ; union NazwaKlasy // Domyślnie publiczna private: protected: public: ;
Tryby dostępu class, struct, union Sekcje private, protected, public; definiują tryb dostępu do poszczególnych elementów sekcji w niej zawartych, tzn. pól i metod (w tym również konstruktora i destruktora). Ich porządek występowania w definicji nie jest ustalony. Mogą występować wielokrotnie i wzajemnie się przeplatać. końcu public. class NazwaKlasy // Domyślnie prywatna protected: private: public: private: ; private dostęp i bezpośrednie odwołanie się do pól i metod tej sekcji możliwy jest tylko z poziomu metod klasy, w której deklarowane i definiowane są te pola i metody. protected dostęp i bezpośrednie odwołanie się do pól i metod tej sekcji możliwy jest z poziomu metod klasy, w której deklarowane i definiowane są te pola i metody. Odwołanie się i bezpośredni dostęp możliwy jest również w klasie pochodnej. public nie ma żadnego ograniczenia na dostęp do pól i metod z tej sekcji.
class, struct, union Definicja klasy z wykorzystaniem słowa kluczowego class class definiuje klasę, która może posiadać wszystkie możliwe atrybuty klasy dostępne w języku C++, tzn. może posiadać metody, konstruktory, destruktory, metody wirtualne, pola i metody statyczne itd. Pozwala na dziedziczenie innych struktur i sama może być dziedziczona. Oprócz tego klasę definiowaną poprzez class można parametryzować tworząc w ten sposób szablony. Domyślną sekcją w definicji klasy jest zawsze sekcja private. class NazwaKlasy //Domyślnie prywatna protected: private: public: ; Przykład definicji: class LZepolona float re, im; public: float Re( ) const return re; float Im( ) const return im; void Zmien(float r, float i); ;
class, struct, union Definicja klasy z wykorzystaniem słowa kluczowego struct struct definiuje klasę, która może posiadać prawie wszystkie możliwe atrybuty klasy dostępne w języku C++, tzn. może posiadać metody, konstruktory, destruktory, metody wirtualne, pola i metody statyczne itd. Pozwala na dziedziczenie innych struktur i sama może być dziedziczona. Jedyne ograniczenie polega na tym, że definiowaną w ten sposób klasę nie można parametryzować, tzn. za jej pomocą nie można tworzyć szablonów. Domyślną sekcją w definicji klasy jest zawsze sekcja public. struct NazwaKlasy //Domyślnie publiczna protected: private: public: ; Przykład definicji: struct LZepolona float Re( ) const return re; float Im( ) const return im; void Zmien(float r, float i); private: float re, im; ;
class, struct, union Definicja klasy z wykorzystaniem słowa kluczowego union union definiuje strukturę, w której każde pole ma ten sam adres. Unia może mieć pola i metody. Nie może mieć natomiast zarówno pól statycznych, jak też metod statycznych. Nie może również posiadać konstruktorów oraz destruktora. Struktura zdefiniowana przez unię może być dziedziczona, ale nie może dziedziczyć innych struktur. Unia nie może też posiadać metod wirtualnych. Domyślną sekcją w definicji klasy jest zawsze sekcja public. union NazwaKlasy //Domyślnie publiczna protected: private: public: ; Przykład definicji: union Wartosc int Absolutna; float Wzgledna; ;
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. double Tab[2][2]; public : double Wez( int i, int j ) const return Tab[i][j]; void Zmien( double elem, int i, int j ) Tab[ i ][ j ] = elem; ;.. float Wyznacznik( const Macierz2x2 &M ) return M. Tab[0][0] M. Tab[1][1] M. Tab[0][1] M. Tab[1][0]; Czy jest to poprawne (i dlaczego nie ;-)?
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. double Tab[2][2]; public : double Wez( int i, int j ) const return Tab[i][j]; void Zmien( double elem, int i, int j ) Tab[ i ][ j ] = elem; ;.. float Wyznacznik( const Macierz2x2 &M ) return M. Tab[0][0] M. Tab[1][1] M. Tab[0][1] M. Tab[1][0]; Poza definicjami metod danej klasy nie można odwoływać się wprost do elementów tej klasy, które znajdują się w sekcji prywatnej. Z tego powodu odwołanie się do pola Tab obiektu M w funkcji Wyznacznik jest niedopuszczalne.
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. protected : double Tab[2][2]; public : double Wez( int i, int j ) const return Tab[i][j]; void Zmien( double elem, int i, int j ) Tab[ i ][ j ] = elem; ;.. float Wyznacznik( const Macierz2x2 &M ) return M. Tab[0][0] M. Tab[1][1] M. Tab[0][1] M. Tab[1][0]; Jeżeli pole zadeklarowane jest w sekcji protected, to bezpośredni dostęp do tego pola poza metodami klasy jest również niemożliwy. Różnice między sekcją public, a protected pojawiają się dopiero przy dziedziczeniu. Dla pojedynczej klasy, która nie jest dziedziczona, sekcje te mają takie samo znaczenie.
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. double Tab[2][2]; public : double Wez( int i, int j ) const return Tab[i][j]; void Zmien( double elem, int i, int j ) Tab[ i ][ j ] = elem; ;.. float Wyznacznik( const Macierz2x2 &M ) return M.Wez(0,0) M.Wez(1,1) M.Wez(0,1) M.Wez(1,0); W sekcji publicznej zdefiniowany jest interfejs do pól klasy Macierz2x2. Pozwala to zachować kontrolę nad sposobem dostępu do tych pól oraz sposobem ich udostępniania. Pozwala to również udostępnić tylko te pola, które chcemy udostępnić.
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. friend float Wyznacznik( const Macierz2x2 &M ); double public : Tab[2][2]; double Wez( int i, int j ) const return Tab[i][j]; void Zmien( double elem, int i, int j ) Tab[ i ][ j ] = elem; ;.. float Wyznacznik( const Macierz2x2 &M ) return M. Tab[0][0] M. Tab[1][1] M. Tab[0][1] M. Tab[1][0]; Pomimo ograniczenia dostępu do pola Tab można uczynić wyjątek dla wybranych funkcji. Pozwala na to deklaracja funkcji zaprzyjaźnionych z daną klasą. Musi ona znaleźć się w obrębie definicji klasy. Miejsce wystąpienia nie jest istotne. Zwyczajowo jednak jest to początek definicji klasy.
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 // float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; //.. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[0][1]; Elem[1][0] = M2. Tab[1][0]; Elem[1][1] = M2. Tab[1][1];
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 // float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; //.. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[0][1]; Elem[1][0] = M2. Tab[1][0]; Elem[1][1] = M2. Tab[1][1]; Ze względu na podobieństwo klas tu jest wszystko poprawnie. Czyż nie?
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 // float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; //.. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[0][1]; Elem[1][0] = M2. Tab[1][0]; Elem[1][1] = M2. Tab[1][1]; Podobieństwo tych klas ma charakter subiektywny. Dla kompilatora to są tak samo różne klasy jak każde inne. Dostęp do pól prywatnych danej klasy nie jest możliwy na poziomie zarówno funkcji jak też metody innej klasy.
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 // friend void Macierz3x3::Wstaw(Macierz2x2); float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; //.. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[0][1]; Elem[1][0] = M2. Tab[1][0]; Elem[1][1] = M2. Tab[1][1]; Dostęp do pól prywatnych staje się możliwy, gdy zaprzyjaźnimy daną metodę z klasą, do której pól prywatnych metody tej klasy mają uzyskać dostęp.
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. friend void Macierz3x3::Wstaw(Macierz2x2); float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //.. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; // Zaprzyjaźnienie jednej metody nie rozwiązuje problemu dostępu do pól prywatnych na poziomie innej metody tej samej klasy. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[0][1]; Elem[1][0] = M2. Tab[1][0]; Elem[1][1] = M2. Tab[1][1]; void Macierz3x3::WstawTrans( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[1][0]; Elem[1][0] = M2. Tab[0][1]; Elem[1][1] = M2. Tab[1][1];
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 //.. friend class Macierz3x3; float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //.. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; // Zaprzyjaźnienie całej klasy pozwala odwoływać się do pól prywatnych na poziomie metod klasy zaprzyjaźnionej. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[0][1]; Elem[1][0] = M2. Tab[1][0]; Elem[1][1] = M2. Tab[1][1]; void Macierz3x3::WstawTrans( Macierz2x2 M2 ) Elem[0][0] = M2. Tab[0][0]; Elem[0][1] = M2. Tab[1][0]; Elem[1][0] = M2. Tab[0][1]; Elem[1][1] = M2. Tab[1][1];
class, struct, union Dostęp do elementów klasy poza klasą class Macierz2x2 // float Tab[2][2]; public : float Wez(int i, int j) const return Tab[i][j]; void Zmien(float elem, int i, int j); ; //.. class Macierz3x3 //. float Elem[3][3]; public : float Wez(int i, int j) const return Elem[i][j]; void Zmien(float elem, int i, int j); void Wstaw(Macierz2x2 M); ; //.. void Macierz3x3::Wstaw( Macierz2x2 M2 ) Elem[0][0] = M2.Wez(0,0); Elem[0][1] = M2.Wez(0,1); Elem[1][0] = M2.Wez(1,0); Elem[1][1] = M2.Wez(1,1); Zaprzyjaźnienie z klasą jest ostatecznością. O ile tylko jest to możliwe należy korzystać z metod wchodzących w skład interfejsu danej klasy.
Pojęcie prywatności class, struct, union class Macierz2x2 //. float Tab[2][2]; public : float Wez( int i, int j ) const return Tab[i][j]; void Zmien( float elem, int i, int j ); void Wstaw( Macierz2x2 M ); ; // void Macierz2x2::Wstaw( Macierz2x2 M ) Tab[0][0] = M. Tab[0][0]; Tab[0][1] = M. Tab[0][1]; Tab[1][0] = M. Tab[1][0]; Tab[1][1] = M. Tab[1][1]; Czy można na poziomie metody danej klasy odwoływać się do pól prywatnych obiektu tej samej klasy?
Pojęcie prywatności class, struct, union class Macierz2x2 //. float Tab[2][2]; public : float Wez( int i, int j ) const return Tab[i][j]; void Zmien( float elem, int i, int j ); void Wstaw( Macierz2x2 M ); ; // void Macierz2x2::Wstaw( Macierz2x2 M ) Tab[0][0] = M. Tab[0][0]; Tab[0][1] = M. Tab[0][1]; Tab[1][0] = M. Tab[1][0]; Tab[1][1] = M. Tab[1][1]; Prywatność nie jest cechą obiektu. Jest to cecha klasy.
Potencjalne możliwości błędów Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; ; //
Potencjalne możliwości błędów Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; ; // int main( ) Stos St; float Arg; if (St. Ilosc >= ROZ STOSU) / Obsługa błędu / St. TabStosu[St. Ilosc++] = 12.3;
Potencjalne możliwości błędów Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; ; // int main( ) Stos St; float Arg; if (St. Ilosc >= ROZ STOSU) / Obsługa błędu / St. TabStosu[St. Ilosc] = 12.3;
Potencjalne możliwości błędów Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; ; // int main( ) Stos St; float Arg; if (St. Ilosc <= 0) / Obsługa błędu / Arg = St. TabStosu[ St. Ilosc];
Potencjalne możliwości błędów Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; ; // int main( ) Stos St; float Arg; if (St. Ilosc <= 0) / Obsługa błędu / Arg = St. TabStosu[ St. Ilosc];
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; ; //
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; float Pobierz( ); ; //
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; float Pobierz( ); ; // float Stos::Pobierz( ) return TabStosu[ Ilosc];
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; float Pobierz( ); ; // float Stos::Pobierz( ) if ( Ilosc <= 0) return numeric limits<float>::max( ); return TabStosu[ Ilosc];
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji #include <limits> using namespace std; struct Stos //.. float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; float Pobierz( ); ; // float Stos::Pobierz( ) if ( Ilosc <= 0) return numeric limits<float>::max( ); return TabStosu[ Ilosc];
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float int TabStosu[ROZ STOSU]; Ilosc; Stos( ) Ilosc = 0; float Pobierz( ); ; // float Stos::Pobierz( ) if ( Ilosc <= 0) return numeric limits<float>::max( ); return TabStosu[ Ilosc];
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // float Stos::Pobierz( ) if ( Ilosc <= 0) return numeric limits<float>::max( ); return TabStosu[ Ilosc]; int main( ) Arg = St.Pobierz( ); if (Arg == numeric limits <float>::max()) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // float Stos::Pobierz( ) if ( Ilosc <= 0) return numeric limits<float>::max( ); return TabStosu[ Ilosc]; int main( ) Arg = St.Pobierz( ); if (Arg == numeric limits <float>::max()) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // float Stos::Pobierz(bool & Sukces ) if ( Ilosc <= 0) Sukces = false; return numeric limits<float>::max( ); return Sukces = true, TabStosu[ Ilosc]; int main( ) Arg = St.Pobierz(CzySukces); if (CzySukces) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // float Stos::Pobierz(bool & Sukces ) if ( Ilosc <= 0) Sukces = false; return numeric limits<float>::max( ); return Sukces = true, TabStosu[ Ilosc]; int main( ) Arg = St.Pobierz(CzySukces); if (CzySukces) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // float Stos::Pobierz(bool & Sukces ) if ( Ilosc <= 0) Sukces = false; return numeric limits<float>::max( ); return Sukces = true, TabStosu[ Ilosc]; int main( ) Arg = St.Pobierz(CzySukces); if (CzySukces) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // bool Stos::Pobierz(float & ZeStosu ) if ( Ilosc <= 0) return false; return ZeStosu = TabStosu[ Ilosc], true; int main( ) Arg = St.Pobierz(CzySukces); if (CzySukces) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // bool Stos::Pobierz(float & ZeStosu ) if ( Ilosc <= 0) return false; return ZeStosu = TabStosu[ Ilosc], true; int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // bool Stos::Pobierz(float & ZeStosu ) if ( Ilosc <= 0) return false; return ZeStosu = TabStosu[ Ilosc], true; Czy takie rozwiązanie pozwala w pełni zabezpieczyć się przed int main( ) błędnym pobraniem wartości ze stosu? if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; int Ilosc; ; // bool Stos::Pobierz(float & ZeStosu ) if ( Ilosc <= 0 ROZ STOSU < Ilosc) return false; return ZeStosu = TabStosu[ Ilosc], true; int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // bool Stos::Pobierz(float & ZeStosu ) if ( Ilosc <= 0 ROZ STOSU < Ilosc) return false; return ZeStosu = TabStosu[ Ilosc], true; int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // bool Stos::Pobierz(float & ZeStosu ) if (! Ilosc ROZ STOSU < Ilosc) return false; return ZeStosu = TabStosu[ Ilosc], true; int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; unsigned int Ilosc; bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); ; //.. int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // float TabStosu[ROZ STOSU]; unsigned int Ilosc; bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); ; //.. int main( ) if (St.Pobierz(Arg)) / Obsługa błędu / St. TabStosu[3] = 5; St. Ilosc;
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); private: float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // int main( ) if (St.Pobierz(Arg)) / Obsługa błędu / St. TabStosu[3] = 5; St. Ilosc;
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); private: float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // int main( ) if (St.Pobierz(Arg)) / Obsługa błędu / St. TabStosu[3] = 5; St. Ilosc;
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); private: float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); unsigned int Ilosc( ) return Ilosc; private: float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Metoda jako element interfejsu klasy Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji struct Stos // bool Pobierz(float& ZeStosu); bool Poloz(float NaStos); unsigned int Ilosc( ) const return Ilosc; private: float TabStosu[ROZ STOSU]; unsigned int Ilosc; ; // int main( ) if (St.Pobierz(Arg)) / Obsługa błędu /
Reprezentacja liczby zespolonej Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji class LZespolona //. float re, im; public : float Re( ) const return re; float Im( ) const return im; float Modul( ) const return re re + im im; void ZmienRI( float re, float im) re = re; im = im; void ZmienMA( float m, float alfa) re = m cos(alfa); im = m sin(alfa); ; //. int main( ) LZespolona Z; Z.ZmienRI(2,5); cout << Modul: << Z.Modul( ) << endl;
Reprezentacja liczby zespolonej Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji class LZespolona //. float re, im; public : float Re( ) const return re; float Im( ) const return im; float Modul( ) const return re re + im im; void ZmienRI( float re, float im) re = re; im = im; void ZmienMA( float m, float alfa) re = m cos(alfa); im = m sin(alfa); ; //. int main( ) LZespolona Z; Z.ZmienRI(2,5); cout << Modul: << Z.Modul( ) << endl; Bezpośrednia reprezentacja części rzeczywistej i urojonej ułatwia implementację operacji dodawania i odejmowania dwóch liczb. Jednak jednocześnie utrudnia realizację operacji mnożenia, dzielenia i wyznaczania modułu.
Reprezentacja liczby zespolonej Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji class LZespolona // float m, alfa; // Kąt wyrażony w radianach public : float Re( ) const return m cos( alfa); float Im( ) const return m sin( alfa); float Modul( ) const return m; void ZmienRI( float re, float im) m = sqrt(re re+im im); alfa = atan2(im,re); void ZmienMA( float m, float alfa) m = m; alfa = alfa; ; // int main() LZespolona Z; Z.ZmienRI(2,5); cout << Modul: << Z.Modul( ) << endl;
Reprezentacja liczby zespolonej Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji class LZespolona // float m, alfa; // Kąt wyrażony w radianach public : float Re( ) const return m cos( alfa); float Im( ) const return m sin( alfa); float Modul( ) const return m; void ZmienRI( float re, float im) m = sqrt(re re+im im); alfa = atan2(im,re); void ZmienMA( float m, float alfa) m = m; alfa = alfa; ; // int main() LZespolona Z; Z.ZmienRI(2,5); cout << Modul: << Z.Modul( ) << endl; Reprezentacja trygonometryczna liczby zespolonej ułatwia implementację operacji mnożenia, dzielenia oraz wyznaczania modułu. Mimo istotnej zmiany wewnętrznej reprezentacji liczby zespolonej na zewnątrz nic się nie zmieniło.
Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji Podsumowanie: Ważniejsze cechy i własności Hermetyzacja pozwala ukryć wewnętrzne cechy implementacji danej klasy. Daje możliwość wydzielenia tej części interfejsu, która realizuje modyfikację obiektu oraz tej, która służy do odczytu stanu obiektu. Umożliwia zdefiniowanie interfejsu, który określa sposób manipulowania wewnętrznymi strukturami obiektu. Pozwala to na zapewnienie spójności wewnętrznych struktur danych. Zapobiega przypadkowej ingerencji w wewnętrzną strukturę obiektu, która mogłaby spowodować utratę spójność przechowywanych danych w obiekcie.
Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji Podsumowanie: Ważniejsze cechy i własności Hermetyzacja pozwala ukryć wewnętrzne cechy implementacji danej klasy. Daje możliwość wydzielenia tej części interfejsu, która realizuje modyfikację obiektu oraz tej, która służy do odczytu stanu obiektu. Umożliwia zdefiniowanie interfejsu, który określa sposób manipulowania wewnętrznymi strukturami obiektu. Pozwala to na zapewnienie spójności wewnętrznych struktur danych. Zapobiega przypadkowej ingerencji w wewnętrzną strukturę obiektu, która mogłaby spowodować utratę spójność przechowywanych danych w obiekcie.
Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji Podsumowanie: Ważniejsze cechy i własności Hermetyzacja pozwala ukryć wewnętrzne cechy implementacji danej klasy. Daje możliwość wydzielenia tej części interfejsu, która realizuje modyfikację obiektu oraz tej, która służy do odczytu stanu obiektu. Umożliwia zdefiniowanie interfejsu, który określa sposób manipulowania wewnętrznymi strukturami obiektu. Pozwala to na zapewnienie spójności wewnętrznych struktur danych. Zapobiega przypadkowej ingerencji w wewnętrzną strukturę obiektu, która mogłaby spowodować utratę spójność przechowywanych danych w obiekcie.
Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji Podsumowanie: Ważniejsze cechy i własności Hermetyzacja pozwala ukryć wewnętrzne cechy implementacji danej klasy. Daje możliwość wydzielenia tej części interfejsu, która realizuje modyfikację obiektu oraz tej, która służy do odczytu stanu obiektu. Umożliwia zdefiniowanie interfejsu, który określa sposób manipulowania wewnętrznymi strukturami obiektu. Pozwala to na zapewnienie spójności wewnętrznych struktur danych. Zapobiega przypadkowej ingerencji w wewnętrzną strukturę obiektu, która mogłaby spowodować utratę spójność przechowywanych danych w obiekcie.
Niebezpieczeństwa struktur bez kontroli dostępu Redukcja możliwych błędów poprzez metody Redukcja możliwych błędów poprzez kontrolę dostępu Zalety hermetyzacji Przykład zastosowania stosu - kalkulator RPN
Formułowanie warunków Hamowanie propagacji błędu Licznik = 0; do ++Licznik; while (Licznik!= MAKS ILOSC); if (Licznik == MAKS ILOSC) cerr << Blad << endl;
Formułowanie warunków Hamowanie propagacji błędu Licznik = 0; do ++Licznik; if ( JakisWarunek ) ++Licznik; while (Licznik!= MAKS ILOSC); if (Licznik == MAKS ILOSC) cerr << Blad << endl;
Formułowanie warunków Hamowanie propagacji błędu Licznik = 0; do ++Licznik; if ( JakisWarunek ) ++Licznik; while (Licznik!= MAKS ILOSC); if (Licznik == MAKS ILOSC) cerr << Blad << endl;
Formułowanie warunków Hamowanie propagacji błędu Licznik = 0; do ++Licznik; if ( JakisWarunek ) ++Licznik; while (Licznik < MAKS ILOSC); if (Licznik >= MAKS ILOSC) cerr << Blad << endl;
Zmienne globalne Zmienne globalne versus zmienne statyczne #include <stdio.h> int IloscPakietow = 0; void WyslijPakiet( ) printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); WyslijPakiet( ); return 0;
Zmienne globalne Zmienne globalne versus zmienne statyczne #include <stdio.h> int IloscPakietow = 0; void WyslijPakiet( ) printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); WyslijPakiet( ); return 0; Pakiet nr: 1 Pakiet nr: 2 Pakiet nr: 3
Zmienne globalne Zmienne globalne versus zmienne statyczne #include <stdio.h> int IloscPakietow = 0; void WyslijPakiet( ) printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); WyslijPakiet( ); return 0; Pakiet nr: 1 Pakiet nr: 2 Pakiet nr: 11
Zmienne globalne Zmienne globalne versus zmienne statyczne #include <stdio.h> int IloscPakietow = 0; void WyslijPakiet( ) printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); IloscPakietow = 10; WyslijPakiet( ); return 0; Pakiet nr: 1 Pakiet nr: 2 Pakiet nr: 11
Zmienne lokalne Zmienne globalne versus zmienne statyczne #include <stdio.h> void WyslijPakiet( ) int IloscPakietow = 0; printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); IloscPakietow = 10; WyslijPakiet( ); return 0;?
Zmienne lokalne Zmienne globalne versus zmienne statyczne #include <stdio.h> void WyslijPakiet( ) int IloscPakietow = 0; printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); IloscPakietow = 10; WyslijPakiet( ); return 0; Pakiet nr: 1 Pakiet nr: 1 Pakiet nr: 1
Zmienne globalne versus zmienne statyczne #include <stdio.h> void WyslijPakiet( ) static int IloscPakietow = 0; printf( Pakiet nr: %i\n,++iloscpakietow); int main( ) WyslijPakiet( ); WyslijPakiet( ); IloscPakietow = 10; WyslijPakiet( ); return 0; w języku C pełnią rolę zmiennych globalnych z ograniczonym zakresem dostępu tylko do poziomu funkcji, w której są deklarowane. Pakiet nr: 1 Pakiet nr: 2 Pakiet nr: 3
Zmienne globalne versus zmienne statyczne #include <iostream> void WyslijPakiet( ) static int IloscPakietow = 0; std::cout << Pakiet nr: << ++IloscPakietow << std::endl; int main( ) WyslijPakiet( ); WyslijPakiet( ); IloscPakietow = 10; WyslijPakiet( ); Identyczne znaczenie mają również w języku C++. Pakiet nr: 1 Pakiet nr: 2 Pakiet nr: 3
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz = 0; int main( ) cout << Lacze1. IloscLacz << endl; Pole statyczne pełni rolę zmiennej globalnej w ramach danej klasy. Istnieje tylko w jednym egzemplarzu niezależnie od wszystkich obiektów.
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz = 0; int main( ) cout << Lacze1. IloscLacz << endl; Musi być zadeklarowane oraz zainicjalizowane poza klasą w przestrzeni zmiennych globalnych. Określony zostaje w ten sposób moment jego utworzenia.
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz; int main( ) cout << Lacze1. IloscLacz << endl; Czy brak inicjalizacji oznacza wartość przypadkową?
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz; int main( ) cout << Lacze1. IloscLacz << endl; Pola statyczne typów wbudowanych zawsze inicjalizowane są wartością 0.
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz; int main( ) cout << LaczeSieciowe:: IloscLacz << endl; Do pola statycznego można odwoływać się bez konieczności tworzenia obiektu, gdyż jest ono własnością klasy, a nie obiektu.
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz; int main( ) LaczeSieciowe Lacze1, Lacze2; Dlatego też każdy z tych trzech sposobów odwołania się do pola IloscLacz jest odwołaniem się do tego samego obszaru pamięci. cout << LaczeSieciowe:: IloscLacz << endl; cout << Lacze1. IloscLacz << endl; cout << Lacze2. IloscLacz << endl;
Pola statyczne w klasie Zmienne globalne versus zmienne statyczne class LaczeSieciowe.. public : static int IloscLacz; LaczeSieciowe( ) ++ IloscLacz; LaczeSieciowe( ) IloscLacz; ;. int LaczeSieciowe :: IloscLacz; int main( ) Aby móc odwołać się do pola statycznego, nie musi istnieć żaden obiekt. Pola statyczne istnieją niezależnie od poszczególnych obiektów. cout << LaczeSieciowe:: IloscLacz << endl;
Koniec prezentacji