Programowanie obiektowe wykład


Programowanie Obiektowe 1
Zakres wykładu
Ć" Programowanie obiektowe w C++
Ć" Programowanie obiektowe w C#
Ć" Projektowanie obiektowe
Ć" Różne technologie obiektowe
Język C++  literatura
Ć" Bjarne Stroustrup  Język C++ , WNT 2002
Ć" Stanley B. Lippman, Josee Lajoie  Podstawy języka C++ , WNT 2001
Ć" Specyfikacja standardu języka C++   draft  2.12.1996
Ć" SGI Standard Template Library Programmer s Guide
http://www.sgi.com/tech/stl/
Programowanie Obiektowe 2
Podstawowe różnice pomiędzy C a C++
Komentarze
1 x = y; /" stary - może być wieloliniowy "/
2 y = z; // nowy - do końca linii
Deklaracje i definicje
Ć" W C++ nie wolno używać niezadeklarowanych funkcji
Ć" Szczególnie istotne staje się dbanie o pliki nagłówkowe
Ć" Deklaracje wewnątrz funkcji nie muszą występować bezpośrednio po
klamerce otwierającej - mogą pojawiać się wewnątrz kodu
î% for (int i=0; i Programowanie Obiektowe 3
Podstawowe różnice pomiędzy C a C++
Deklaracje struktur
Ć" tworzą  pełnoprawne typy (nie potrzeba typedef):
Przy następującej deklaracji typu:
1 struct DwaPola {
2 int pole1;
3 double pole2;
4 };
w języku C zmienne deklarujemy przez:
1 struct DwaPola x;
a w języku C++ można przez:
1 DwaPola x;
Programowanie Obiektowe 4
Podstawowe różnice pomiędzy C a C++
Referencje (typ &)
Ć" zmienne referencyjne  odnośniki do innych zmiennych, muszą być od
razu inicjowane:
1 int x;
2 int &refx = x;
3 double &cos = nazwaStr.nazwaPola->iJeszczeCos;
Ć"  trzeci sposób przekazywania argumentów do funkcji
Ć" w zapisie jak zwykłe przekazanie przez wartość, w działaniu jak
przekazanie adresu do zmiennej
Ć" podobne funkcjonowanie jak w przypadku Pascal owego przekazywania
argumentu przez zmiennÄ…
Programowanie Obiektowe 5
Referencje (typ &) - Przykład
W C zawsze przez wartość (wartością może być wskaznik):
1 void swap(int x, int y) 1 void swap(int "x, int "y)
2 { 2 {
3 int z = x; 3 int z = "x;
4 x = y; 4 "x = "y;
5 y = z; 5 "y = z;
6 } 6 }
W C++ można tak:
1 void swap(int &x, int &y)
2 {
3 int z = x;
4 x = y;
5 y = z;
6 }
Programowanie Obiektowe 6
Podstawowe różnice pomiędzy C a C++
Domyślne wartości argumentów funkcji
Ć" deklaracja
1 Wielomian Pochodna(Wielomian fun, int ktora=1);
Ć" definicja
1 Wielomian Pochodna(Wielomian fun, int ktora) {
2 if (ktora>1)
3 return Pochodna(Pochodna(fun, ktora-1));
4 else
5 for (int i=Stopien(fun); i>0; i--)
6 ...
7 }
Ć" wartość domyślną można podać w definicji o ile nie było deklaracji
Ć" jeśli pewien argument ma wartość domyślną, to muszą ją mieć również
kolejne argumenty
Programowanie Obiektowe 7
Strumienie, operatory << i >>
Ć" #include
lub
1 #include
2 using namespace std;
Ć" Obiekty standardowego wejścia/wyjścia: cin, cout, cerr.
Ć" Klasy istream, ostream, ifstream, ofstream, istrstream, . . .
Ć" Przykład:
1 cout << "Proszę o wartość x: ";
2 cin >> x;
3 cout << "zmienna x ma wartość" << x << endl;
4 char napis[100];
5 cin.getline(napis, 100);
6 cout << napis;
Ć" Formatowanie przez metody klas lub manipulatory.
Programowanie Obiektowe 8
Manipulatory i metody
Manipulator Metoda
showpos setf(ios_base::showpos)
noshowpos unsetf(ios_base::showpos)
showbase setf(ios_base::showbase)
noshowbase unsetf(ios_base::showbase)
uppercase setf(ios_base::uppercase)
nouppercase unsetf(ios_base::uppercase)
showpoint setf(ios_base::showpoint)
noshowpoint unsetf(ios_base::showpoint)
boolalpha setf(ios_base::boolalpha)
noboolalpha unsetf(ios_base::boolalpha)
unitbuf setf(ios_base::unitbuf)
nounitbuf unsetf(ios_base::unitbuf)
internal setf(ios_base::internal,ios_base::adjustfield)
Programowanie Obiektowe 9
Manipulator Metoda
left setf(ios_base::left,ios_base::adjustfield)
right setf(ios_base::right,ios_base::adjustfield)
dec setf(ios_base::dec,ios_base::basefield)
hex setf(ios_base::hex,ios_base::basefield)
oct setf(ios_base::oct,ios_base::basefield)
fixed setf(ios_base::fixed,ios_base::floatfield)
scientific setf(ios_base::scientific,ios_base::floatfield)
resetiosflags(ios_base::fmtflags) setf(0,flag)
setiosflags(ios_base::fmtflags) setf(flag)
setbase(int base) see above
setfill(char_type c) fill(c)
setprecision(int n) precision(n)
setw(int n) width(n)
endl EOL and flush
ends EOS and flush
flush flush()
Programowanie Obiektowe 10
Funkcjonalność iostream i iomanip
1 #include
2 #include
3 using namespace std;
4 void main ( )
5 {
6 int i; float f;
7 cin >> i >> f; // read an integer and a float from stdin
8 cout << i << endl; // output the integer and goes at the line
9 cout << f << endl; // output the float and goes at the line
10 cout << hex << i << endl; // output i in hexa
11 cout << oct << i << dec << i << endl; // output i in octal and then in decimal
12 cout << showpos << i << endl; // output i preceded by its sign
13 cout << setbase(16) << i << endl; // output i in hexa
14 // output i in dec and pad to the left with character
15 // @ until a width of 20
16 // if you input 45 it outputs 45@@@@@@@@@@@@@@@@@@
17 cout << setfill( @ ) << setw(20) << left << dec << i << endl;
Programowanie Obiektowe 11
18 // output the same result as the code just above
19 // but uses member functions rather than manipulators
20 cout.fill( @ );
21 cout.width(20);
22 cout.setf(ios_base::left, ios_base::adjustfield);
23 cout.setf(ios_base::dec, ios_base::basefield);
24 cout << i << endl;
25 // outputs f in scientific notation with
26 // a precision of 10 digits
27 cout << scientific << setprecision(10) << f << endl;
28 // change the precision to 6 digits
29 // equivalents to cout << setprecision(6);
30 cout.precision(6);
31 // output f and goes back to fixed notation
32 cout << f << fixed << endl;
33 }
Programowanie Obiektowe 12
Klasy i obiekty
Ć" definicja, pola i funkcje (metody)
1 class Wielomian
2 {
3 int st;
4 double "wsp;
5 Wielomian Pochodna(int ktora=1);
6 };
Ć" definicje metod
1 Wielomian Wielomian::Pochodna(int ktora)
2 {
3 if (ktora == 1)
4 for (int i=st; i>0; i--)
5 ...
6 else return Pochodna().Pochodna(ktora-1);
7 }
Programowanie Obiektowe 13
Modyfikatory dostępu
Ć" dostęp do wnętrza klasy (information hiding): public, protected, private
1 class Wielomian
2 {
3 private :
4 int st;
5 double "wsp;
6
7 public :
8 int Stopien() {return st;}
9 Wielomian Pochodna(int ktora=1);
10 };
11 Wielomian w; // deklaracja w zewnętrznej funkcji
12 w.st; // nie wolno
13 w.Stopien(); // czemu nie
Programowanie Obiektowe 14
Struktury  też klasy
Ć" struktury to klasy o publicznym dostępie  w klasach domyślny modyfikator
dostępu to private
1 class nazwa
1 struct nazwa
2 {
2 {
== 3 public :
3 ...
4 ...
4 };
5 };
Ć" struktury z modyfikatorami dostępu niczym nie różnią się od klas
Programowanie Obiektowe 15
Konstruktory i destruktory
Ć" Konstruktory, destruktory, konstruktory kopiujące  tworzą i likwidują
obiekty
î% konstruktorów może być wiele (różne konteksty), a destruktor zawsze
tylko jeden
î% konstruktor = metoda o nazwie takiej jak nazwa klasy
î% destruktor = metoda o nazwie skÅ‚adajÄ…cej siÄ™ z tyldy (~) i nazwy klasy
î% konstruktory mogÄ… być prywatne!
Ć" cykl życia obiektu
przydzielenie pamiÄ™ci konstrukcja ···
··· destrukcja zwolnienie pamiÄ™ci
Programowanie Obiektowe 16
Konstruktory i destruktor klasy wielomianów
1 class Wielomian
2 {
3 private :
4 int st;
5 double "wsp;
6 public :
7 Wielomian Pochodna(int ktora=1);
8 Wielomian(); // Konstruktor
9 Wielomian(int st, double "wsp); // Konstruktor
10 Wielomian(Wielomian &); // Konstruktor kopiujÄ…cy
11 ~Wielomian(); // Destruktor
12 };
Programowanie Obiektowe 17
Konstruktory c.d.
1 void DeklaracjeWielomianow(void)
2 {
3 double tab[] = {2, 5, 16, 0, 12, 4};
4 int n = sizeof(tab)/sizeof("tab);
5 Wielomian w1; // konstruktor bezargumentowy
6 Wielomian w2(n, tab); // konstruktor z argumentami
7 Wielomian w3(w2); // konstruktor kopiujÄ…cy
8 Wielomian w4 = w2; // Uwaga! też konstruktor kopiujący
9 ...
10 }
Destruktory wołane są automatycznie w odpowiednim czasie  tutaj na
zakończenie funkcji DeklaracjeWielomianow.
Programowanie Obiektowe 18
Tablice obiektów
Ć" przy inicjowaniu i zwalnianiu pamięci konstruktor (bezargumentowy) jest
wołany dla każdego obiektu z tablicy
Ć" dynamiczny przydział pamięci  operatory new i delete (delete[])
1 int "x = new int[100];
2 int k;
3 scanf("%d", &k);
4 Wielomian "w = new Wielomian[k];
5 Wielomian "v = new Wielomian(st, wsp);
6 ...
7 delete x; // BÅ‚Ä…d - nie zwolnimy wszystkiego
8 delete[] w; // OK
9 delete v; // OK
Programowanie Obiektowe 19
Implementacje konstruktorów
Ć" wewnątrz klasy:
1 class Wielomian
2 { ... double "wsp; ...
3 Wielomian() {
4 st = 0;
5 wsp = new double[1];
6 "wsp = 0;
7 }
8 };
Ć" na zewnątrz:
1 Wielomian::Wielomian() {
2 st = 0;
3 wsp = new double[1];
4 "wsp = 0;
5 }
Programowanie Obiektowe 20
Implementacje destruktorów
Ć" wewnątrz klasy:
1 class Wielomian
2 {
3 ...
4 double "wsp;
5 ...
6 ~Wielomian() { delete[] wsp; }
7 };
Ć" na zewnątrz:
1 Wielomian::~Wielomian()
2 {
3 delete[] wsp;
4 }
Programowanie Obiektowe 21
Wskaznik this
Ć" wskaznik this to wskaznik do obiektu na którym zawołano daną metodę
(do wykorzystania tylko w metodach klas)
1 Wielomian &Wielomian::RazyStala(double stala)
2 {
3 for (int i=0; i<=st; i++)
4 wsp[i] "= stala;
5 return "this;
6 }
7
8 main()
9 {
10 double wsp[] = {3.0, 2.0, 1.0};
11 Wielomian w(sizeof(wsp)/sizeof("wsp), wsp);
12 w.RazyStala(2).RazyStala(3);
13 Wielomian w2 = w.Pochodna();
14 }
Programowanie Obiektowe 22
Wskaznik this
Ć"  Odkrywanie pola przykrytego zmienną
1 Wielomian::Wielomian(int st, double "wsp)
2 {
3 this->st = st;
4 for (int i=0; i<=st; i++)
5 ...
6 }
Ć" przekazywanie wskaznika funkcjom zewnętrznym
1 String::String(char "s)
2 {
3 str = new char[strlen(s)+1];
4 strcpy(str, s);
5 stringMgr->RejestrPamieci(this, s);
6 }
Programowanie Obiektowe 23
Friends czyli przyjaciele
Ć" friends  przyjaciele  klasy i funkcje zadeklarowane jako przyjaciele mają
pełen dostęp do prywanych i chronionych pól i funkcji klasy
1 class Wielomian {
2 ...
3 friend class PrzestrzenWielomianow;
4 friend Wielomian Dodaj(Wielomian &, Wielomian &);
5 friend void Menedzer::Zarzadzaj(Wielomian &);
6 };
7 Wielomian Dodaj(Wielomian &w1, Wielomian &w2) {
8 Wielomian wynik = w1;
9 for (int i=0; i<=w2.st; i++)
10 wynik.wsp[i] += w2.wsp[i];
11 return wynik;
12 }
Ć" Najlepiej trzymać się z dala od przyjaciół!
Programowanie Obiektowe 24
l-wartości i r-wartości
Ć" wszystkie zmienne i wartości stałe leżą w pamięci, ale nie zawsze są w
pełni adresowalne
Ć" l-wartość  ang. lvalue, location value
î% to wartość, która jest odwoÅ‚aniem do konkretnego miejsca w pamiÄ™ci
î% w zamyÅ›le  wartość, która może stać po lewej stronie instrukcji
przypisania
î% wyjÄ…tek: staÅ‚a to też l-wartość, ale nie może stać po lewej stronie
Ć" r-wartość  ang. rvalue, read value
î% to dowolna wartość wyrażenia  mamy dostÄ™p do wartoÅ›ci, ale
niekoniecznie do adresu pod którym leży
î% przykÅ‚ady: staÅ‚e użyte w wyrażeniach, tymczasowe zmienne
przechowujące wyniki wyrażeń
î% wartość, która może stać po prawej stronie instrukcji przypisania
Programowanie Obiektowe 25
l-wartości i r-wartości  c.d.
Ć" niepoprawne wyrażenia:
1 1 = 5+3;
2 sqrt(x) = 17;
3 int &x = 2; // potrzebna l-wartość z prawej strony
Ć" niepoprawne wywołania funkcji
1 void f (int &x)
2 {
3 x = 2"2;
4 }
5 main()
6 {
7 f(3+4); // nie można, bo 3+4 daje wartość tymczasową
8 }
Programowanie Obiektowe 26
Ć" niepoprawne wywołania metod
1 class Wielomian
2 {
3 ...
4 friend Wielomian Dodaj(Wielomian &, Wielomian &);
5 };
6
7 main()
8 {
9 Wielomian w1, w2, w3;
10 w3 = Dodaj(w1,w2); // błąd! Dodaj() wymaga l-wartości
11 Dodaj(w1, Dodaj(w2, w3)); // też błąd wynik Dodaj() to nie l-wartość
12 }
Programowanie Obiektowe 27
Obiekty tymczasowe i referencje do stałych (const &)
Ć" powstają przy wyliczaniu wartości wyrażeń (wyniki częściowe), zwracaniu
wartości funkcji itp.
Ć" żyją do czasu wyliczenia pełnego wyrażenia w którym występują
Ć" mogą inicjalizować stałe referencyjne lub deklarowane obiekty, wtedy żyją
tak długo jak to co zainicjowały
1 const int &x = 5;
2 const int &n = 4+3;
3 const Wielomian &w = Dodaj(w1, w2); // ok
Programowanie Obiektowe 28
Obiekty tymczasowe  przykład Stroustrupa
1 string s1, s2, s3;
2 const char" cs= (s1+s2).c_str() ;
3 cout << cs; // może się uda...
4 if (strlen(cs=(s2+s3).c_str())<8 && cs[0]==´a´) {
5 // chcesz użyć cs? powodzenia...
6 }
Tak czy inaczej to bardzo brzydki styl programowania.
Programowanie Obiektowe 29
Polimorfizm  przeciążanie operatorów
Ć" pomysł nie całkiem nowy:
1 5 + 17 5.0 + 17.0
2 5 / 17 5.0 / 17
Ć" operatory, które można przeciążać
1 + - " / % ^ & | ~ !
2 = < > += -= "= /= %= ^= &=
3 |= << >> >>= <<= == != <= >= &&
4 | | ++ -- ->" , -> [ ] ( ) new delete
Ć" nie można tworzyć własnych operatorów
Ć" nie można definiować operatorów o ww nazwach ale z inną liczbą
argumentów niż oryginalnie
Programowanie Obiektowe 30
Przeciążanie operatorów  deklaracje
Operatory, których pierwszym argumentem jest obiekt pewnej klasy mogą być
zadeklarowane jako niezależne lub wewnątrz tej klasy:
Ć" niezależnie (na zewnątrz klasy)  często warto by taki operator był
zaprzyjazniony z klasÄ…:
1 class Wielomian
2 {
3 ...
4 friend Wielomian operator+(const Wielomian &, const Wielomian &);
5 };
6
7 Wielomian operator+(const Wielomian &w1, const Wielomian &w2)
8 {
9 ...
10 }
Programowanie Obiektowe 31
Ć" wewnątrz klasy (pierwszy argument operatora ukryty  to obiekt
wywołujący):
1 class Wielomian
2 {
3 ...
4 Wielomian operator+(const Wielomian &);
5 };
6
7 Wielomian Wielomian::operator+(const Wielomian &w)
8 {
9 ...
10 stopien = max(st, w.st);
11 }
Ć" przykłady deklaracji operatorów:
1 double operator[](int index);
2 Wielomian &operator=(const Wielomian &);
3 int operator==(const Wielomian &, const Wielomian &);
Programowanie Obiektowe 32
Przeciążanie operatorów  dwie szkoły
Ć" Szkoła 1:
î% jeÅ›li tylko siÄ™ da (pierwszy argument tego typu) to wewnÄ…trz klasy, np:
1 Wielomian &operator+=(const Wielomian &);
2 Wielomian operator+(const Wielomian &);
3 int operator==(const Wielomian &);
Ć" Szkoła 2:
î% wewnÄ…trz klasy te, które sÄ… w szczególny sposób zwiÄ…zane z jednym
obiektem definiowanej klasy, np:
1 Wielomian &operator+=(const Wielomian &);
î% jeÅ›li operator w sposób równorzÄ™dny dotyczy dwóch obiektów tego
typu, to sprawiedliwie jest umieścić go poza klasą, np:
1 Wielomian operator+(const Wielomian &, const Wielomian &);
2 int operator==(const Wielomian &, const Wielomian &);
Programowanie Obiektowe 33
Przeciążanie operatorów  c.d.
Ć" Uwaga na referencje!
Ć" Najlepiej by definiowany operator był logicznie maksymalnie bliski
oryginalnego znaczenia
Ć" Operator indeksowania  przede wszystkim dla tablic
1 int IntArray::operator[](int index);
Ć" Operator wywołania funkcji  klasy w roli funkcji
1 JakisTyp Klasa::operator()(/" argumenty"/);
Ć" Operator wskazywania  niby obiekt, a jak wskaznik
1 InnaKlasa "Klasa::operator->();
Programowanie Obiektowe 34
Ć" Operator przypisania  szczególne znaczenie gdy pamięć przydzielana jest
dynamicznie
1 class Wektor
2 {
3 int wymiar;
4 double "wsk;
5 public:
6 Wektor(int _wymiar);
7 Wektor(const Wektor &w);
8 ~Wektor();
9 Wektor &operator=(const Wektor &w);
10 double &operator[](int index);
11 };
Programowanie Obiektowe 35
1 Wektor::~Wektor()
2 {
3 delete[] wsk;
4 }
5 Wektor &Wektor::operator=(const Wektor &w)
6 {
7 wymiar = w.wymiar;
8 delete[] wsk;
9 wsk = new double[wymiar];
10 memcpy(wsk, w.wsk, wymiar"sizeof("wsk));
11 }
12 Wektor::Wektor(const Wektor &w)
13 {
14 wsk = 0;
15 "this = w;
16 }
Programowanie Obiektowe 36
Ć" Operatory konwersji typów, np:
1 operator int();
2 operator double();
3 operator char "();
Przyklad:
1 class MyString
2 {
3 char "str;
4 public:
5 MyString(char "s);
6 operator char"() {return str;}
7 };
8 main() {
9 char str[20];
10 MyString s("Ala");
11 strcpy(str, s);
12 }
Programowanie Obiektowe 37
Ć" Operatory ++ i --
1 Typ operator++(); // przedrostkowy
2 Typ operator++(int); // przyrostkowy
Należy unikać zbyt skomplikowanych wyrażeń, w tym takich, które stosują
operatory ++ bądz -- do zmiennych, występujących w wyrażeniu więcej
niż raz.
Przykład nieintuicyjnego działania kompilatora:
1 int id(int x) {return x;}
2 main() {
3 int z = 2;
4 cout << z + z++ << endl; 1 4
5 z = 2; generuje wyjście 2 5
6 cout << z + id(z++) << endl; 3 5
7 z = 2;
8 cout << id(z++) + z << endl;
9 }
Programowanie Obiektowe 38
Operatory dla wielomianów
1 class Wielomian
2 {
3 ...
4 public :
5 Wielomian &operator=(const Wielomian &);
6 Wielomian &operator"=(double c);
7 Wielomian &operator"=(const Wielomian &);
8 };
9 Wielomian operator"(const Wielomian &, double c);
10 Wielomian operator"(const Wielomian &, const Wielomian &);
Programowanie Obiektowe 39
1 Wielomian &Wielomian::operator=(const Wielomian &w)
2 {
3 st = w.st;
4 /" można tak
5 for (int i=0; i6 wsp[i] = w.wsp[i];
7 "/
8 // ale jest lepsze rozwiÄ…zanie:
9 for (double "w1=wsp+st+1,"w2=w.wsp+st+1; w1-->wsp;)
10 "w1 = "--w2;
11 return "this;
12 }
Programowanie Obiektowe 40
1 Wielomian &Wielomian::operator"=(double c)
2 {
3 for (double "w=wsp+st+1; w-->wsp;)
4 "w "= c;
5 return "this;
6 }
7
8 Wielomian Wielomian::operator"(const Wielomian &w, double c)
9 {
10 Wielomian ww(w);
11 /" Tak nie, bo 1. nie ma sensu powielać, 2. potrzeba by zaprzyjaznienia
12 for (int i=0; i13 ww.wsp[i] "= c; "/
14 ww "= c; // Tak łatwiej i mniej miejsca na błędy
15 return w;
16 }
Programowanie Obiektowe 41
Strumienie, operatory << i >>
Ć" Dociążanie operatorów wewnątrz własnych klas:
1 class Cos
2 {
3 public:
4 ostream &operator <<(ostream &o)
5 {return o << "coÅ›";}
6 };
Lepiej nie, bo wychodzÄ… dziwactwa:
1 main()
2 {
3 Cos z;
4 cout << z; // błąd kompilacji
5 z << cout; // OK, ale chyba nie o to chodziło
6 z << cout << " i coÅ› jeszcze"; // a fuj!
7 }
Programowanie Obiektowe 42
Ć" Dociążanie operatorów na zewnątrz własnych klas:
1 ostream &operator <<(ostream &o, Cos &obiekt)
2 {
3 return o << "coÅ›";
4 }
Teraz pełny porządek:
1 main()
2 {
3 Cos z;
4 z << cout; // błąd kompilacji - i bardzo dobrze
5 cout << z; // OK
6 cout << z << " i coÅ› jeszcze"; // OK
7 }
Programowanie Obiektowe 43
Ć" Dociążanie operatorów strumieniowych  uwaga na styl!
î% Zwracamy istream& lub ostream&, bo inaczej:
1 void operator <<(ostream &o, Cos &obiekt)
2 {
3 o << "coÅ›";
4 }
5 main()
6 {
7 Cos z;
8 cout << z << " i coś jeszcze"; // błąd kompilacji
9 }
Programowanie Obiektowe 44
Operatory bez rozrzutności  const & raz jeszcze
1 class Zespolona
2 {
3 public:
4 double re;
5 double im
6 Zespolona(double r, double i);
7 Zespolona(const Zespolona &z);
8 Zespolona operator=(const Zespolona &z);
9 };
10 Zespolona operator+(const Zespolona &z1, const Zespolona &z2) { ... }
11 void main() {
12 Zespolona z1(0,0), z2(1,1), z3(2,2);
13 z3 = z1+z2+z3;
14 }
Konstruktor kopiujący wołany raz  bez const & w operatorze + aż 4 razy!
Programowanie Obiektowe 45
static w języku C
Ć" zmienna globalna ograniczona do modułu
1 static int x;
î% widoczna tylko w ramach jednego pliku
î% różne pliki mogÄ… deklarować zmienne statyczne o tej samej nazwie nie
powodując konfliktów przy scalaniu programu
Ć" zmienna w funkcji
1 void funkcja(void) {
2 static int licznik = 0;
3 licznik++;
4 ...
5 }
î% pamięć przydzielona i inicjowana przy pierwszym wywoÅ‚aniu i
zwalniana na zakończenie programu
î% zawartość  żyje pomiÄ™dzy kolejnymi wywoÅ‚aniami funkcji
Programowanie Obiektowe 46
static w C++  pola statyczne
Ć" pola statyczne (static class members) to pola dzielone przez wszystkie
obiekty danej klasy
1 class Wielomian
2 {
3 static int ileObiektow;
4 public:
5 Wielomian() {ileObiektow++;}
6 };
7 int Wielomian::ileObiektow = 0;
Ć" jeden dla wszystkich, co oznacza, że modyfikacja pola w dowolnym
obiekcie zmienia to pole we wszystkich pozostałych
Ć" publiczne pole statyczne jest niemal równoważne zmiennej globalnej
dostępnej przez Klasa::pole
Ć" oprócz deklaracji w klasie niezbędna jest deklaracja na zewnątrz
(ewentualnie z inicjalizacjÄ…)
Programowanie Obiektowe 47
Przykład klasy wektorów bitowych
1 class WektorBitowy
2 {
3 unsigned int "bity;
4 int rozmiar;
5
6 public :
7 WektorBitowy(int rozmiar);
8 ~WektorBitowy();
9
10 WektorBitowy &operator+=(int nrBitu); // WÅ‚Ä…cz bit
11 WektorBitowy &operator-=(int nrBitu); // Wyłącz bit
12 int operator[](int nrBitu); // Czy bit jest włączony
13
14 WektorBitowy &operator|=(const WektorBitowy &);
15 WektorBitowy &operator&=(const WektorBitowy &);
Programowanie Obiektowe 48
16 ...
17 friend WektorBitowy operator|(const WektorBitowy &,
18 const WektorBitowy &);
19 ...
20 };
21
22 WektorBitowy::WektorBitowy(int rozmiar)
23 {
24 WektorBitowy::rozmiar = rozmiar/(sizeof(int)"8)+1;
25 bity = new int[WektorBitowy::rozmiar];
26 }
27
28 WektorBitowy::~WektorBitowy()
29 {
30 delete[] bity;
31 }
Programowanie Obiektowe 49
PoczÄ…tek projektowania obiektowego
Przykład: Model silnika samochodu wraz z niezbędnymi okolicami
Obiekty  części stanowiące odrębną całość z pewną wyraznie określoną
funkcjonalnością:
Ć" akumulator
Ć" stacyjka
Ć" rozrusznik
Ć" silnik
î% koÅ‚o zamachowe
î% waÅ‚ korbowy
î% popychacze, zawory, cylindry, . . .
Ć" alternator
Ć" . . .
Programowanie Obiektowe 50
PoczÄ…tek projektowania obiektowego  c.d.
Zadania klas
Ć" Wyodrębnienie osobnych elementów funkcjonalnych
Ć" Zamknięcie w jedną całość wartości opisujących obiekt i metod
funkcjonowania obiektu
Przykład: stacyjka
î% pozycja kluczyka
î% funkcja zmiany poÅ‚ożenia kluczyka  stacyjka.przeÅ‚Ä…cz():
" przekaż prąd układowi zapłonu  układZapłonu.zasil()
" przekaż prąd rozrusznikowi  rozrusznik.zasil()
Ć" Możliwość wielokrotnego użycia klasy  wiele podobnych obiektów
Przykład: cylindry, korbowody, tłoki, zawory, świece zapłonowe,
przekazniki
Ć" Ułatwienie projektowania aplikacji  dziel i zwyciężaj  wyodrębniaj
klasy/obiekty i implementuj zredukowany zakres funkcji
Programowanie Obiektowe 51
Dziedziczenie, klasy pochodne
1 class IntArray
2 {
3 int dim;
4 int "values;
5 public :
6 IntArray() : dim(0), values(0) {}
7 IntArray(int Dim) : dim(Dim) {values = new int[dim];}
8 // ...
9 int operator[](int index) {return values[index];}
10 };
11 class IntSortArray : public IntArray
12 {
13 public :
14 IntSortArray(int Dim) : IntArray(dim) {}
15 };
Programowanie Obiektowe 52
Dziedziczenie  kontrola dostępu
dziedziczenie w klasie bazowej
public protected private
public public protected 
protected protected protected 
private private private 
Programowanie Obiektowe 53
Hierarchie klas
Czasowy Pracownik
Sekretarz Kierownik
CzasowySekretarz
Konsultant Dyrektor
1 class Czasowy { /" ... "/ };
2 class Pracownik { /" ... "/ };
3 class Sekretarz : public Pracownik { /" ... "/ };
4 class Kierownik : public Pracownik { /" ... "/ };
5 class CzasowySekretarz
6 : public Czasowy, public Sekretarz { /" ... "/ };
7 class Konsultant
8 : public Czasowy, public Kierownik { /" ... "/ };
Programowanie Obiektowe 54
Wielokrotne dziedziczenie
Osoba Osoba
Czasowy Pracownik
Sekretarz Kierownik
CzasowySekretarz
Rozstrzyganie niejednoznaczności
1 // Osoba posiada metodÄ™ Nazwisko()
2 // Czasowy i Pracownik posiadajÄ… metody Wynagrodzenie()
3 CzasowySekretarz p;
4 p.Wynagrodzenie(); // BÅ‚Ä…d
5 p.Czasowy::Wynagrodzenie(); // OK
6 p.Pracownik::Wynagrodzenie(); // OK
7 p.Osoba::Nazwisko(); // BÅ‚Ä…d
Programowanie Obiektowe 55
Wirtualne klasy bazowe
Osoba
Czasowy Pracownik
Sekretarz Kierownik
CzasowySekretarz
1 class Czasowy : public virtual Osoba { /" ... "/ };
2 class Pracownik : public virtual Osoba { /" ... "/ };
3 class Sekretarz : public Pracownik { /" ... "/ };
4 class CzasowySekretarz
5 : public Czasowy, public Sekretarz { /" ... "/ };
Programowanie Obiektowe 56
Wirtualne klasy bazowe  c.d.
Ć" Jedna kopia obiektu klasy bazowej
Ć" Konstruktor wirtualnej klasy bazowej musi być wołany przez konstruktor
każdej klasy potomnej
1 CzasowySekretarz::CzasowySekretarz(???)
2 : Czasowy(???), Sekretarz(???),
3 Osoba(???)
4 {
5 ...
6 }
Inaczej mielibyśmy niejednoznaczność, bo każda z klas Czasowy i
Sekretarz może inaczej inicjować obiekt typu Osoba.
Programowanie Obiektowe 57
Ć" Uwaga na transformacje typów wskazników:
1 CzasowySekretarz "p;
2 Czasowy "pt = (Czasowy ")p;
3 Sekretarz "ps = (Sekretarz ")p;
4 Osoba "po = (Osoba ")p;
Założenie merytorycznej poprawności tych konwersji łatwo prowadzi do
sprzeczności  obiekty różnych typów pod tym samym adresem!
RozwiÄ…zanie: wykorzystanie Runtime Type Identification (RTTI), ale o
tym pózniej.
Programowanie Obiektowe 58
Metody wirtualne
1 class Figura {
2 public :
3 virtual void Obroc(int);
4 virtual void Rysuj();
5 void Skaluj(float wsp);
6 ...
7 };
8 class Okrag : public Figura {
9 int x, y;
10 int promien;
11 public :
12 void Obroc(int);
13 void Rysuj();
14 void Skaluj(float wsp);
15 };
Programowanie Obiektowe 59
1 void main()
2 {
3 Okrag o;
4 Figura "f = &o;
5 f->Skaluj(0.5); // woła Figura::Skaluj()
6 f->Rysuj(); // woła Okrag::Rysuj()
7 }
Uwagi:
Ć" Metody wirtualne wołane w konstruktorze są uruchamiane jak niewirtualne
(obiekt potomny jeszcze nie istnieje - a dokładniej nie został zainicjowany -
więc nie może działać)
Ć" Wirtualne metody zwiększają rozmiary klas (odpowiednie adresy do funkcji
muszą być przechowywane razem z obiektem)
Programowanie Obiektowe 60
Bardziej realna postać problemu:
1 void SkalujIRysuj(Figura "f)
2 {
3 f->Skaluj();
4 f->Rysuj();
5 }
6 void main()
7 {
8 Okrag o;
9 ...
10 SkalujIRysuj(&o);
11 }
Programowanie Obiektowe 61
Wirtualne destruktory
1 class Figura {
2 public :
3 ...
4 virtual ~Figura() {}
5 };
6 class ListaFigur {
7 Figura "figura[1000];
8 int ileFigur;
9 public:
10 ...
11 ~ListaFigur(); // zwalnia pamięć po wszystkich figurach
12 void Dodaj(Figura ");
13 void Rysuj();
14 };
Programowanie Obiektowe 62
1 ListaFigur::~ListaFigur() {
2 for (int i=0; i3 delete figura[i];
4 }
5 void ListaFigur::Rysuj() {
6 for (int i=0; i7 figura[i]->Rysuj();
8 }
9
10 void DwieFigury()
11 {
12 ListaFigur l;
13 l.Dodaj(new Okrag(30, 20, 15));
14 l.Dodaj(new Kwadrat(5, 5, 25));
15 l.Rysuj();
16 }
Programowanie Obiektowe 63
Kolejność wywołań konstruktorów i destruktorów
Ć" konstruktory od klasy pierwotnej do  najbardziej potomnej
Ć" destruktory w odwrotnej kolejności
Ć" w dziedziczeniu wielokrotnym konstruktory są wołane w porządku
odpowiadajÄ…cym deklaracji dziedziczenia
Ć" konstruktory obiektów będących polami klasy są wołane po konstruktorze
klasy, w której występują, w kolejności, w jakiej pojawiają się w deklaracji
klasy
Ć" inicjalizacja pól może być umieszczona w sposób analogiczny do wywołań
konstruktorów klas bazowych (musi w sytuacji, kiedy klasa pola-obiektu ma
tylko konstruktory z niepomijalnymi argumentami)
Ć" z destruktorami mamy sytuację analogiczną
Ć" wirtualne klasy bazowe są zawsze inicjowane przed niewirtualnymi
Programowanie Obiektowe 64
 Czyste klasy wirtualne (abstrakcyjne)
1 class Figura {
2 public :
3 virtual void Obroc(int) = 0;
4 virtual void Rysuj() = 0;
5 };
6 void main() {
7 Figura f; // BÅ‚Ä…d
8 }
Ć" Nie da się stworzyć obiektu typu abstrakcyjnego
Ć" Mechanizm interfejsów (Pascal/Delphi, technologie MS Windows: ActiveX
itp.)
Programowanie Obiektowe 65
Wzorce (ang. templates)
Przykład zapotrzebowania - minimum
Ć" wiele funkcji  nieprzyjemne...
1 int min(int arg1, int arg2) {
2 return arg1 < arg2? arg1 : arg2;
3 }
4 double min(double arg1, double arg2) {
5 return arg1 < arg2? arg1 : arg2;
6 }
Ć" #define  niebezpieczeństwo wielokrotnego liczenia
1 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
2 ...
3 z = MIN(x.LiczDuzo(),1000);
4 // rozwinięte zostanie do:
5 z = (((x.LiczDuzo())<(1000)) ? (x.LiczDuzo()) : (1000));
Programowanie Obiektowe 66
Wzorce funkcji
1 template
2 T Min(T arg1, T arg2)
3 {
4 return arg1 < arg2? arg1 : arg2;
5 }
6 void main()
7 {
8 int i=5, j=10;
9 double x=1.9, y=3;
10 cout << Min(i,j) << endl; // 5 T == int
11 cout << Min(x,y) << endl; // 1.9 T == double
12 cout << Min(x+y,x-y) << endl; // -1
13 }
Programowanie Obiektowe 67
Wzorce klas
1 template class Stos
2 {
3 int rozmiar;
4 TypObiektu "pocz, "wierz;
5 public:
6 Stos(int r) {pocz = wierz = new TypObiektu[rozmiar = r];}
7 ~Stos() {delete[] pocz;}
8
9 void Odloz(TypObiektu o) {"wierz++ = o;}
10 TypObiektu Pobierz() {return "--wierz;}
11 };
Programowanie Obiektowe 68
Wzorce  użycie klasy Stos
1 void main()
2 {
3 int i;
4 Stos stos(100);
5 for (i=0; i<20; i++)
6 stos.Odloz(i"i);
7 for (i=0; i<20; i++)
8 cout << stos.Pobierz() << "\n";
9 }
Programowanie Obiektowe 69
Wzorce  wektor dowolnego typu
1 template
2 class Array
3 {
4 protected :
5 int dim;
6 T "values;
7 public :
8 Array() {values = new T[dim=d];}
9 ~Array() {delete[] values;}
10 T &operator[](int index);
11 };
Ć" Lepiej definiować wymiar w konstruktorze  tak jak było dla stosu
Programowanie Obiektowe 70
Wzorce  definicja metody
1 template
2 T &Array::operator[](int index)
3 {
4 if (index <0 || index >=dim)
5 exit(1);
6 return values[index];
7 }
Programowanie Obiektowe 71
Wzorce  dziedziczenie
1 typedef int CompareFun(const void "arg1, const void "arg2);
2
3 template
4 class SortArray : public Array
5 {
6 public :
7 void QuickSort(CompareFun "f);
8 };
9
10 template
11 class IntArray : public Array
12 {
13 public :
14 ...
15 };
Programowanie Obiektowe 72
WyjÄ…tki (exceptions)
Ć" Zgłaszanie wyjątków
1 throw 123;
2 throw "Nie wiem co się stało";
3 throw ExceptionTypeObject;
4 throw WyjatekZOpisem("Przekroczenie zakresu!");
Ć" Deklaracje klas dla wyjątków
1 class TypWyjÄ…tku {};
2 struct WyjatekZOpisem
3 {
4 string opis;
5 WyjatekZOpisem(char "o) {opis = o;}
6 };
Programowanie Obiektowe 73
Ć" Przechwytywanie wyjątków
1 try
2 {
3 lista instrukcji
4 }
5 catch (ExceptionType o)
6 {
7 lista instrukcji
8 }
9 catch (...)
10 {
11 lista instrukcji
12 }
Programowanie Obiektowe 74
Ć" Przechwytywanie wyjątków  więcej informacji
1 try
2 {
3 DuzoLiczenia();
4 }
5 catch (ExceptionType o)
6 {
7 Komunikat(o.opis);
8 }
9 catch (...)
10 {
11 Komunikat("Nieznany błąd w funkcji DuzoLiczenia()");
12 }
Programowanie Obiektowe 75
Ć" Przechwytywanie wyjątków  niebezpieczeństwo wycieków pamięci
1 try
2 {
3 Zadanie "z = new Zadanie();
4 z->PoliczWszystko();
5 delete z;
6 }
7 catch (...)
8 {
9 Komunikat("Coś się stało i z nie zwolniony :-(");
10 }
Programowanie Obiektowe 76
Ć" Przechwytywanie wyjątków  sprzątamy niezależnie czy wystąpił wyjątek
czy nie
1 Zadanie "z=0; // to zerowanie jest ważne
2 try
3 {
4 z = new Zadanie();
5 z->PoliczWszystko();
6 }
7 __finally
8 {
9 delete z;
10 Komunikat("I posprzÄ…tane :-)");
11 }
Programowanie Obiektowe 77
WyjÄ…tki (exceptions)
Ć" Typy wyjątków wewnątrz klas
1 class NazwaKlasy
2 {
3 ...
4 class TypWyjÄ…tku {};
5 }
Wówczas przechwytywanie wyjątków wygląda tak:
1 catch (NazwaKlasy::TypWyjÄ…tku x)
2 {
3 ...
4 }
Programowanie Obiektowe 78
Wyjątki  prosty przykład
1 #include
2
3 class ArgumentSilni{};
4
5 long Silnia(int x)
6 {
7 if (x < 0) throw ArgumentSilni();
8 return (x <= 1)? 1 : x " Silnia(x-1);
9 }
10
11 main()
12 {
13 int arg;
14 try
15 {
Programowanie Obiektowe 79
16 while (1)
17 {
18 printf("Podaj argument : ");
19 scanf("%d", &arg);
20 printf("%d! = %ld\n", arg, Silnia(arg));
21 }
22 }
23 catch (ArgumentSilni x)
24 {
25 printf("Niepoprawny argument dla funkcji Silnia().\n");
26 return 1;
27 }
28 catch (...)
29 {
30 printf("Nie obsługiwany wyjątek.\n");
31 return 2;
32 }
33 }
Programowanie Obiektowe 80
Operator ::
Ć" funkcje przykrywające zmienne
1 int x;
2 int funkcja(float x) {
3 x = 4; // typ float i lokalna zmienna x
4 ...
5 return 0;
6 }
Ć" zmienna globalna jest dostępna przed deklaracją ją przykrywającą
1 int x;
2 int funkcja() {
3 x = 5; // zmienna globalna - typ int
4 ...
5 float x;
6 x = 4; // zmienna lokalna - typ float
7 }
Programowanie Obiektowe 81
Ć" Operator :: daje dostęp do przykrytej zmiennej globalnej
1 int x = 5;
2 int funkcja()
3 {
4 float x;
5 ...
6 x = ::x;
7 ...
8 }
Programowanie Obiektowe 82
Przestrzenie nazw  namespaces
Ć" Przykład:
1 namespace A {
2 void cokolwiek() {cout << "jesteśmy w przestrzeni A";}
3 }
4 namespace B {
5 void cokolwiek() {cout << "jesteśmy w przestrzeni B";}
6 }
7 main() {
8 cokolwiek(); // BÅ‚Ä…d! Funkcja niezdefiniowana.
9 A::cokolwiek(); // OK
10 B::cokolwiek(); // OK
11 }
Programowanie Obiektowe 83
Ć" otwieranie bezpośredniego dostępu do przestrzeni nazw:
1 using namespace A;
Po otwarciu przestrzeni A:
1 main() {
2 cokolwiek(); // OK - funkcja przestrzeni A
3 A::cokolwiek(); // OK
4 B::cokolwiek(); // OK
5 }
Programowanie Obiektowe 84
Ć" otwieranie wszystkich możliwych przestrzeni jest równie uciążliwe jak nie
otwieranie żadnej:
1 using namespace A;
2 using namespace B;
3 main() {
4 cokolwiek(); // Błąd! Dwuznaczność.
5 A::cokolwiek(); // OK
6 B::cokolwiek(); // OK
7 }
Ć" funkcje definiowane bez jawnej deklaracji przestrzeni to funkcje w
podstawowej przestrzeni nazw (o pustej nazwie  dostęp przez ::id)
Ć" definiując bibliotekę należy utworzyć dla niej własną przestrzeń nazw
Programowanie Obiektowe 85
Metody typu inline
1 template class Vector
2 {
3 T"data;
4 int size;
5 public:
6 Vector(int s) {data=new T[size=s];}
7 ~Vector() {delete[] data;}
8 inline T &operator[] (int i);
9 int Size() {return size;}
10 };
11
12 template T &operator[] (int i)
13 {
14 return data[i];
15 }
Ć" Uwaga na opcje kompilatora blokujące wywołania inline!
Programowanie Obiektowe 86
Wskazniki do funkcji
1 #include // dla printf()
2 #include // dla qsort()
3 #include // dla strcmp() i stricmp()
4
5 typedef int ("Funkcja)(char"", char"");
6
7 int Porownaj1(char""s1, char""s2) {
8 return strcmp("s1,"s2);
9 }
10 int Porownaj2(char""s1, char""s2) {
11 return stricmp("s1,"s2);
12 }
13 int Porownaj3(char""s1, char""s2) {
14 if (strlen("s1) > strlen("s2)) return 1;
15 if (strlen("s1) < strlen("s2)) return -1;
16 return 0;
17 }
Programowanie Obiektowe 87
18
19 void main()
20 {
21 int i, j;
22 char"ala[] = {"ALA MA KOTA", "Ala ma Kota", "alamakota", "Ala"};
23 Funkcja f[] = {Porownaj1, Porownaj2, Porownaj3};
24 for (i=0; i25 printf("Wynik[%d] = %d\n", i, f[i](ala, ala+1));
26 for (i=0; i27 {
28 qsort(ala, sizeof(ala)/sizeof("ala), sizeof("ala), f[i]);
29 printf("\nPo sortowaniu nr %d\n", i);
30 for (j=0; j31 printf("%s\n", ala[j]);
32 }
33 }
Programowanie Obiektowe 88
Wskazniki do pól i metod, operatory .* i ->*
1 class A
2 {
3 public:
4 int z;
5 int fun(int x) {return x = 0;}
6 };
7
8 typedef int A::"Aint;
9 typedef int (A::"FUN)(int);
10
11 int F(A x, int A::"ai) {
12 return x."ai;
13 }
14 int Fp(A "x, Aint ai) {
15 return x->"ai;
Programowanie Obiektowe 89
16 }
17 int G(A x, FUN f) {
18 return (x."f)(12);
19 }
20 int Gp(A "x, FUN f) {
21 return (x->"f)(12);
22 }
23
24 int main()
25 {
26 A a;
27 int A::"c = &A::z;
28 F(a, c);
29 Fp(&a, &A::z);
30 G(a, A::fun);
31 Gp(&a, A::fun);
32 return 0;
33 }
Programowanie Obiektowe 90
Stałe a klasy  const
1 const int x=5;
2 const int y; // Błąd! Stała niezainicjowana
3 const Macierz Id5(5);
4 const int v[] = {1, 2, 3, 4}; // każde v[i] jest stałe
5
6 main()
7 {
8 Id5.Rzad(); // OK
9 Id5.Triangularyzacja(); // BÅ‚Ä…d! Metoda zmienia obiekt
10 }
Dodanie const to stworzenie nowego typu
1 const char" pc; // wskaznik na stały znak
2 char "const cp; // stały wskaznik na znak
3 char const" pc2; // wskaznik na stały znak
Programowanie Obiektowe 91
const w deklaracjach argumentów funkcji
1 char" strcpy(char" p, const char" q); // nie można zmienić "q
Deklaracje metod wywoływalnych również dla stałych:
1 class Macierz
2 {
3 int ileKolumn;
4 public:
5 int Rzad() const;
6 int IleKolumn() const {return ileKolumn;}
7 ...
8 };
Programowanie Obiektowe 92
Pola zmienne (mutable)
Ć" Czasami istnieje potrzeba modyfikacji pewnych pól  organizacyjnych w
obiektach deklarowanych jako stałe
î% wÅ‚aÅ›ciwa reprezentacja obiektu nie zmienia siÄ™, ale mogÄ… zmieniać siÄ™
pewne dane związane z obsługą
î% np. Obiekt daty i obsÅ‚uga cache u z datÄ… jako napisem:
1 class Date {
2 mutable bool cache_valid;
3 mutable char cache[20];
4 void compute_cache_value() const; // fill cache
5 public:
6 char "string_rep() const; // string representation
7 // ...
8 };
Programowanie Obiektowe 93
1 char "Date::string_rep() const
2 {
3 if (cache_valid == false) {
4 compute_cache_value();
5 cache_valid = true;
6 }
7 return cache;
8 }
Ć" Uwaga! Funkcje deklarowane dla obiektów stałych mogą zmieniać pola
statyczne.
Programowanie Obiektowe 94
Ć" Można też brutalnie:
1 class Date {
2 bool cache_valid;
3 char cache[20];
4 void compute_cache_value(); // fill cache
5 public:
6 char"string_rep() const; // string representation
7 ...
8 };
9 char"Date::string_rep() const
10 {
11 if (cache_valid == false) {
12 Date"th = (Date")this;
13 th->compute_cache_value();
14 th->cache_valid = true;
15 }
16 return cache;
17 }
Programowanie Obiektowe 95
Obiekty ulotne (volatile)
Ć" Deklaracja zmiennej jako volatile informuje kompilator, że wartość
zmiennej może się zmieniać w tle (w innym wątku)
Ć" Zakaz pewnych uproszczeń (optymalizacji) dla takich zmiennych
Ć" Kompilator nie może przechowywać zmiennej tylko w rejestrze.
Ć" Przykład:
1 volatile int ticks;
2 void timer( ) { ticks++; }
3 void wait (int interval) {
4 ticks = 0;
5 while (ticks < interval); // Nie rób nic
6 }
Optymalizator mógłby zignorować polecenie wielokrotnego sprawdzania
warunku, bo nic siÄ™ nie zmienia.
Ć" Uwaga: W C++ ulotne mogą być również metody klas  w ulotnym
obiekcie można używać tylko ulotnych metod.
Programowanie Obiektowe 96
Zakresy życia obiektów
Ć" obiekty globalne  zaczynają przed main(), kończą po main()
Ć" pola statyczne klas  jak obiekty globalne
Ć" pola niestatyczne  jak obiekt, w którym występują tj. od konstruktora do
destruktora
Ć" zmienne lokalne dla funkcji  od momentu deklaracji, do końca zakresu
(klamry kończącej blok)
Ć" parametry funkcji  zaczynają bezpośrednio przed wywołaniem funkcji,
kończą po zakończeniu działania funkcji
Ć" zmienne deklarowane w for  zakres pętli
Ć" zmienne tymczasowe (powstające podczas wyliczania wartości wyrażeń) 
od momentu konieczności przechowania wyniku cząstkowego do końca
wyznaczania wartości wyrażenia
Programowanie Obiektowe 97
Różne drobne uwagi
Ć" elipsy (. . . ) a klasy
Uwaga: Argument przekazany funkcji o zmiennej liczbie argumentów nie
może być obiektem klasy, która definiuje konstruktor albo operator = (ale
oczywiście może być wskaznikiem do takiej klasy)
Ć" Członkowie unii nie mogą implementować konstruktorów ani destruktorów
Ć" Konstruktory obiektów globalnych wołane są przed wywołaniem funkcji
main()
Ć" Jeśli klasa ma wirtualne funkcje, to zwykle powinna mieć też wirtualny
destruktor
Ć" Kolejność wyliczania podwyrażeń w wyrażeniu jest niezdefiniowana!
Programowanie Obiektowe 98
RTTI
RunTime Type Identification pozwala:
Ć" (w trakcie działania programu) poznać typ danych, kiedy dysponujemy
tylko wskaznikiem
Ć" na kontrolowaną konwersję wskaznika klasy bazowej na wskaznik klasy
potomnej  operator dynamic_cast
Ć" sprawdzić, czy wskazywany obiekt jest pewnego znanego nam typu 
operator typeid
Programowanie Obiektowe 99
Operator typeid
1 typeid( expression )
2 typeid( type-name )
Ć" zwraca referencję na obiekt typu const type_info
Ć" klasa type_info implementuje
î% operator==
î% operator!=
î% metodÄ™ const char "name() const;
î% metodÄ™ bool before(const type_info &) const;
Ć" jeśli argument jest wskaznikiem, to wynikiem jest identyfikacja
dynamicznego typu obiektu (odpowiedniego obiektu potomnego)
Ć" działa ze standardowymi typami i klasami użytkownika
Ć" Jeśli argument jest wskaznikiem zerowym, to zgłaszany jest wyjątek
Bad_typeid
Programowanie Obiektowe 100
1 class A { };
2 class B : A { };
3 void main() {
4 char C; float X;
5
6 if (typeid(C) == typeid(X)) cout << "Ten sam typ." << endl;
7 else cout << "Nie ten sam typ." << endl;
8
9 cout << typeid(int).name()
10 << " before " << typeid(double).name() << ": "
11 << typeid(int).before(typeid(double)) << endl;
12
13 cout << "double before int: "
14 << typeid(double).before(typeid(int)) << endl;
15
16 cout << typeid(A).name()
17 << " before " << typeid(B).name() << ": "
18 << typeid(A).before(typeid(B)) << endl;
19 }
Programowanie Obiektowe 101
Wyjście programu:
Nie ten sam typ.
int before double: 0
double before int: 1
A before B: 1
Programowanie Obiektowe 102
Nowe metody konwersji typów
Ć" const_cast(arg)
Ć" dynamic_cast(arg)
Ć" reinterpret_cast(arg)
Ć" static_cast(arg)
Oczywiście, stare sposoby konwersji (te z C) również działają.
Programowanie Obiektowe 103
const_cast(arg)
Ć" dodaje lub zdejmuje modyfikator const lub volatile
Ć" const_cast(arg), typy Typ oraz arg muszą być takie same z
dokładnością do modyfikatorów
Ć" konwersja w czasie kompilacji
Ć" dowolna liczba modyfikatorów może być zniesiona bądz dodana jedną
konwersjÄ…
Ć" nie wymaga RTTI
Przykład:
1 void ZmienStala(const int &x)
2 {
3 int &z = const_cast(x);
4 z = 123;
5 }
Możliwe, ale bardzo nieładne...
Programowanie Obiektowe 104
dynamic_cast(arg)
Ć" Typ  typ wskaznikowy (w tym void ") bądz referencyjny
Ć" arg  wyrażenie dające w wyniku wskaznik lub referencję (odpowiednio do
Typ)
Ć" jeśli Typ to void ", to wynikiem jest wskaznik na obiekt najbardziej
potomnej klasy
Ć" konwersje z klasy potomnej do bazowej są wykonywane w czasie
kompilacji, w drugą stronę lub  na przełaj hierarchii  w trakcie działania
programu
Ć" konwersja do klasy potomnej możliwa tylko dla klas polimorficznych
Ć" w przypadku powodzenia dynamic_cast(arg) zwraca odpowiedni
wskaznik,
Ć" w przypadku porażki:
î% zwraca 0 dla wskazników
î% zgÅ‚asza wyjÄ…tek Bad_cast dla referencji
Ć" wymaga RTTI
Programowanie Obiektowe 105
1 class Base1 {
2 virtual void f(void) { /"klasa polimorficzna"/ }
3 };
4 class Base2 { };
5 class Derived : public Base1, public Base2 { };
6
7 int main(void) {
8 try {
9 Derived d,"pd;
10 Base1"b1 = &d;
11
12 // W dół hierarchii - z Base1 do derived
13 if ((pd = dynamic_cast(b1)) != 0)
14 {
15 cout << "Wynikowy wskaznik jest typu "
16 << typeid(pd).name() << std::endl;
17 }
18 else
19 throw Bad_cast();
Programowanie Obiektowe 106
20
21 // "Na przełaj" - z jednej bazowej do drugiej
22 Base2"b2;
23 if ((b2 = dynamic_cast(b1)) != 0) {
24 cout << "Wynikowy wskaznik jest typu "
25 << typeid(b2).name() << endl;
26 }
27 else throw Bad_cast();
28 }
29 catch (Bad_cast) {
30 cout << "dynamic_cast nie powiodło się" << endl;
31 return 1;
32 }
33 catch (...) {
34 cout << "Nieznany wyjÄ…tek!" << endl;
35 return 1;
36 }
37 return 0;
38 }
Programowanie Obiektowe 107
reinterpret_cast(arg)
Ć" zmienia interpretację bitowej reprezentacji obiektu
Ć" Typ  wskaznik, referencja, typ arytmetyczny, wskaznik do funkcji lub
wskaznik do składowej
Ć" wskaznik może być jawnie przekonwertowany do typu całkowitego
Ć" liczba całkowita może być konwertowana do wskaznika
Ć" można konwertować na wskaznik bądz referencję na nie zdefiniowany
jeszcze typ
Ć" poleca się używać w zamian za jawną konwersję np. (int ")x
Programowanie Obiektowe 108
1 void func(void "v) {
2 // Ze wskaznika do liczby całkowitej
3 int i = reinterpret_cast(v);
4 ...
5 }
6
7 void main() {
8 // Z liczby całkowitej do wskaznika
9 func(reinterpret_cast(5));
10
11 // ze wskaznika do funkcji na wskaznik
12 // do funkcji innego typu
13 typedef void (" PFV)();
14
15 PFV pfunc = reinterpret_cast(func);
16
17 pfunc();
18 }
Programowanie Obiektowe 109
static_cast(arg)
Ć" Typ  wskaznik, referencja, typ arytmetyczny lub wyliczeniowy (enum)
Ć" zarówno Typ jak i arg muszą być w pełni znane w czasie kompilacji
Ć" jeśli konwersja może być wykonana środkami języka, to konwersja przez
static_cast robi to samo
Ć" liczby całkowite mogą być konwertowane do typu wyliczeniowego, dla
wartości spoza zakresu zachowanie niezdefiniowane
Ć" wskaznik na jeden typ może być konwertowany na wskaznik na inny typ
Ć" wskaznik do klasy Y może być konwertowany do wskaznika do klasy X,
jeśli Y dziedziczy po X  konwersja możliwa jeśli:
î% istnieje jednoznaczny sposób konwersji z Y do X
î% X nie jest dziedziczona wirtualnie przez Y
Programowanie Obiektowe 110
static_cast(arg)  c.d.
Ć" obiekt może być przekonwertowany do X&, o ile wskaznik do niego może
być przekonwertowany do X". Wynik jest l-wartością. Nie są wołane
żadne konstruktory ani operatory konwersji.
Ć" obiekt lub wartość można przekonwertować na obiekt pewnej klasy, jeśli
istnieje odpowiedni konstruktor bÄ…dz operator konwersji
Ć" wskaznik do składowej może być przekonwertowany na inny wskaznik do
składowej, jeśli oba wskazują składowe tej samej klasy, bądz różnych klas,
ale z jednoznacznym dziedziczeniem pomiędzy nimi
Programowanie Obiektowe 111
Rozszerzenia Borland C++ Buildera
Typy
Typ Przykład Rozmiar
__int8 __int8 c = 127i8; 8 bitów
__int16 __int16 s = 32767i16; 16 bitów
__int32 __int32 i = 123456789i32; 32 bity
__int64 __int64 big = 12345654321i64; 64 bity
unsigned __int64 unsigned __int64 hugeInt = 64 bity
1234567887654321ui64;
SÅ‚owa kluczowe
Ć" __closure
Ć" __property
Ć" __published
Ć" __thread
Ć" i wiele innych, których opis można znalezć w systemie pomocy Borland
C++ Buildera (C++ Builder Language Guide)
Programowanie Obiektowe 112
__closure
Ć" Pozwala zadeklarować specjalny rodzaj wskaznika do metody
Ć" Standard C++ pozwala jedynie na pełną specyfikację jak na stronie 89 i w
poniższym przykładzie:
1 class base
2 {
3 public:
4 int func(int x) { return x; }
5 };
6 typedef int (base::" pBaseMember)(int);
7
8 void main()
9 {
10 base baseObject;
11 pBaseMember m = base::func;
12 (baseObject."m)(17);
13 }
Programowanie Obiektowe 113
Ć" Standard C++ nie pozwala na to, by takiemu wskaznikowi przypisać adres
do metody klasy potomnej:
1 class derived : public base
2 {
3 public:
4 int new_func(int x) { return 2"x; }
5 };
6 int main(int argc, char" argv[])
7 {
8 derived derivedObject;
9 pBaseMember m = derived::new_func; // BÅ‚Ä…d! Ale:
10 pBaseMember m = (pBaseMember)(&derived::new_func); // OK
11 }
Programowanie Obiektowe 114
Ć" __closure definiuje wskaznik do metody związanej z konkretnym obiektem
Ć" Zależności hierarchii klas nie mają znaczenia  tylko liczba i typy
argumentów oraz typ zwracanej wartości.
Ć" Przykład nazwiązujący do poprzednich:
1 int main(int argc, char" argv[])
2 {
3 derived derivedObject;
4 int (__closure "derivedClosure)(int);
5 derivedClosure = derived::new_func; // BÅ‚Ä…d!
6 derivedClosure = derivedObject.new_func; // OK
7 derivedClosure(3); // derivedObject.new_func(3);
8 return 0;
9 }
Programowanie Obiektowe 115
Ć" __closure działa również dla wskazników:
1 void func1(base "pObj)
2 {
3 void (__closure "myClosure)(int);
4 myClosure = pObj->func;
5 myClosure(1);
6 return;
7 }
8
9 int main(int argc, char" argv[])
10 {
11 derived derivedObject;
12 void (__closure "derivedClosure)(int);
13 derivedClosure = derivedObject.new_func;
14 derivedClosure(3);
15 func1(&derivedObject);
16 return 0;
17 }
Programowanie Obiektowe 116
Ć" __closure to podstawa Borlandowego środowiska RAD (Rapid
Application Development)  zarówno w Delphi jak i C++ Builderze 
pozwala przypisywać funkcje obsługi zdarzeń poszczególnym obiektom.
Ć" Przykłady:
î% zdarzenie OnClick dla obiektu klasy TButton
î% zdarzenie OnChange dla obiektu klasy TEdit
î% zdarzenie OnMouseMove dla obiektu dowolnej klasy dziedziczÄ…cej po
TControl
Programowanie Obiektowe 117
__property
Zapotrzebowanie:
Ć" Często chronimy pola, ale tworzymy publiczne metody do ich obsługi. Na
przykład:
1 class XYZ {
2 int rozmiar;
3 char "bufor;
4 public:
5 ...
6 int Rozmiar() {return rozmiar;}
7 void UstawRozmiar(int r) {rozmiar = r;
8 delete[] bufor; bufor = new char[rozmiar];}
9 };
Ć" Żmudne i trzeba pamiętać nazwy albo stosować zawsze ten sam schemat
(np. GetXX() i SetXX()).
Programowanie Obiektowe 118
Aadniejsze rozwiązanie z użyciem __property
1 class XYZ {
2 int _rozmiar;
3 char "bufor;
4 int Rozmiar() {return _rozmiar;}
5 void UstawRozmiar(int r) {_rozmiar = r;
6 delete[] bufor; bufor = new char[_rozmiar];}
7 public:
8 ...
9 __property int rozmiar = {read = Rozmiar,
10 write = UstawRozmiar};
11 /" albo "/
12 __property int rozmiar = {read = _rozmiar,
13 write = UstawRozmiar};
14 };
Wówczas instrukcja x.rozmiar = 5; jest równoważna wywołaniu
x.UstawRozmiar(5);.
Programowanie Obiektowe 119
Syntaktyka __property:
1 __property type propertyName[index1Type index1]
2 [indexNType indexN] = { attributes };
gdzie
î% type jest pewnym znanym typem (standardowym lub wczeÅ›niej
zdefiniowanym),
î% propertyName jest identyfikatorem,
î% indexNType jest pewnym znanym typem (standardowym lub wczeÅ›niej
zdefiniowanym),
î% indexN jest nazwÄ… parametru (indeksu) przekazywanego funkcjom read i
write,
î% attributes jest listÄ… oddzielonych przecinkami deklaracji read, write,
stored, default (lub nodefault) lub index.
Parametry indexN są opcjonalne  definiują własności tablicowe.
Programowanie Obiektowe 120
Przykłady deklaracji __property:
1 class PropertyExample {
2 private:
3 int Fx,Fy;
4 float Fcells[100][100];
5 protected:
6 int readX() {return(Fx);}
7 void writeX(int newFx) {Fx = newFx;}
8 double computeZ() {/" ... "/ return(0.0);}
9 float cellValue(int row, int col)
10 {return(Fcells[row][col]);}
11 public:
12 __property int X = {read=readX, write=writeX};
13 __property int Y = {read=Fy};
14 __property double Z = {read=computeZ};
15 __property float Cells[int row][int col] =
16 {read=cellValue};
17 };
Programowanie Obiektowe 121
Przykład wykorzystania
1 PropertyExample pe;
2
3 pe.X = 42; // pe.writeX(42);
4 int myVal1 = pe.Y; // myVal1 = pe.Fy;
5 double myVal2 = pe.Z; // myVal2 = pe.ComputeZ();
6 float cellV = pe.Cells[3][7]; // cellV = pe.cellValue(3,7);
Własności mogą także:
Ć" przypisywać te same metody czytania i pisania do różnych własności
(z użyciem atrybutu index)
Ć" mieć wartości domyślne
Ć" być zapamiętywane w plikach opisu okien bądz nie
Ć" być rozszerzane w klasach potomnych
Ć" . . .
Programowanie Obiektowe 122
__published
Ć" Wykorzystywane przez środowisko RAD Borlanda
Ć" Własności pojawiające się w tej sekcji są wyświetlane przez inspektora
obiektów (Object Inspector)
Ć" Tylko klasy dziedziczące po TObject mogą deklarować sekcję
__published.
Ć" Dostępność składowych jest taka sama jak tych z sekcji public. Różnice są
jedynie w sposobie generowania informacji dla RTTI.
Ć" W sekcji __published nie można deklarować
î% konstruktorów, destruktorów,
î% pól tablicowych,
î% obiektów typów innych niż porzÄ…dkowe, rzeczywiste, Å‚aÅ„cuchowe,
zbiorowe, klasowe i wskazujące na składowe.
Programowanie Obiektowe 123
__thread
Ć" Programowanie wielowątkowe  równolegle wykonywane wątki programu.
Ć" Zmienne globalne w programowaniu wielowątkowym
î% Zagrożenie problemami wielodostÄ™pu.
î% Prosty i atrakcyjny mechanizm komunikacji miÄ™dzy wÄ…tkami
Ć" Czasami bardzo przydatne mogą być zmienne globalne w ramach wątku,
ale nie współdzielone przez różne wątki. Modyfikator __thread:
int __thread x;
deklaruje zmiennÄ… jako lokalnÄ… dla wÄ…tku, a zarazem globalnÄ… w ramach
wÄ…tku.
Ć" Modyfikator __thread może być użyty tylko dla zmiennych globalnych i
statycznych.
Ć" Wskazniki i zmienne typu funkcyjnego nie mogą być lokalnymi dla wątków.
Ć" Typy, które używają techniki  copy-on-write (jak AnsiString) mogą być
niebezpieczne jako typy zmiennych lokalnych dla wÄ…tku.
Programowanie Obiektowe 124
Ć" Zmienna wymagająca inicjalizacji bądz finalizacji w trakcie działania
programu nie może być deklarowana jako __thread.
î% zmienna inicjalizowana poprzez wywoÅ‚anie funkcji:
1 int f();
2 int __thread x = f(); // BÅ‚Ä…d!
î% obiekty typów klasowych definiujÄ…cych konstruktor bÄ…dz destruktor
1 class X {
2 X();
3 ~X();
4 };
5 X __thread myclass; // BÅ‚Ä…d!
Programowanie Obiektowe 125
Projektowanie obiektowe
Ć" Zrozumienie zadania
Ć" Algorytmy i struktury danych
Ć" Implementacja
Przykład: Zadanie Alice & Bob  konkurs programowania zespołowego ACM
 Europa Centralna 2001
Programowanie Obiektowe 126
Technika top-down - zaczynamy od funkcji main()
1 void main()
2 {
3 int ileZadan;
4 ZadanieAB ab;
5 fstream input("ab.in");
6 fstream output("ab.out", ios::out);
7
8 input >> ileZadan;
9 for (int i=0; i10 {
11 input >> ab;
12 ab.Rozwiaz();
13 output << ab;
14 }
15 }
Programowanie Obiektowe 127
Schemat klasy rozwiÄ…zujÄ…cej zadanie:
1 class ZadanieAB
2 {
3 // Podstawowe dane
4 int n, m; // liczby wierzchołków i przekątnych
5 Odcinki o; // tablica odcinków
6 // Rezultaty
7 bool sukces;
8 int "numer; // numery kolejnych wierzchołków
9
10 public:
11 bool Rozwiaz();
12
13 friend istream& operator>>(istream& is, ZadanieAB &ab);
14 friend ostream& operator<<(ostream& os, const ZadanieAB &ab);
15 };
Programowanie Obiektowe 128
Szablony a przyjaciele
Ć" Norma języka nie przewiduje problemów.
Ć" Niestety, konkretne implementacje w problemy obfitują.
1 template
2 class task {
3 // ...
4 friend void next_time();
5 friend task" preempt(task");
6 friend task" prmt(task"); // task is task
7 friend class task;
8 // ...
9 };
Programowanie Obiektowe 129
Zaprzyjazniony operator  outline
1 template
2 class TempOp
3 {
4 T x;
5 public :
6 friend
7 ostream &operator <<(ostream &os, const TempOp &to);
8 };
9 template
10 ostream &operator <<(ostream &os, const TempOp &to)
11 {
12 os << to.x << endl;
13 return os;
14 }
Ć" Zgodne ze standardem, ale g++ akceptuje, u Borlanda problemy linkera!
Programowanie Obiektowe 130
Zaprzyjazniony operator  inline
1 template
2 class TempOp
3 {
4 T x;
5 public :
6 friend
7 ostream &operator <<(ostream &os, const TempOp &to)
8 {
9 os << to.x << endl;
10 return os;
11 }
12 };
Ć" Zgodne ze standardem i akceptowane przez Borland C++ i g++.
Programowanie Obiektowe 131
inline z ponownÄ… deklaracjÄ… szablonu
1 template
2 class TempOp
3 {
4 T x;
5 public :
6 template
7 friend
8 ostream &operator <<(ostream &os, const TempOp

&to)
9 {
10 os << to.x << endl;
11 return os;
12 }
13 };
Ć" Może działać, ale nie jest to właściwa definicja.
Programowanie Obiektowe 132
Ć" Działa, gdy mamy jedną specjalizację klasy:
1 TempOp i;
2 cout << i;
Ć" Przestaje, gdy mamy więcej specjalizacji:
1 TempOp to;
2 TempOp i;
3 cout << to;
4 cout << i;
Kompilator zgłasza niejednoznaczność.
Programowanie Obiektowe 133
STL  Standard Template Library
Ć" Teraz już jest częścią standardu języka.
Ć" Implementacja SGI http://www.sgi.com/tech/stl/ 
wykorzystywana m.in. w Borland C++.
Ć" Implementuje szablony wielu bardzo przydatnych struktur danych i
algorytmów:
î% Kontenery: vector, deque, list, set, multiset, map, multimap, oraz
dodatkowo w implementacji SGI:
hash_set, hash_multiset, hash_map, hash_multimap.
î% Iteratory
î% Algorytmy: reverse, find, for_each, sort . . .
Programowanie Obiektowe 134
vector
Ć" Przykład:
1 vector v;
2 v.reserve(100);
3 for (unsigned i=0; i<100; i++)
4 v[i] = i"i;
5 v.push_back(117);
6 for (unsigned i=0; i7 cout << v[i] << endl;
Ć" Parametry:
T  typ elementów wektora
Alloc  alokator pamięci
Programowanie Obiektowe 135
Ć" Wybrane składowe:
reference typ: referencja na T
pointer typ: wskaznik na T
iterator typ do iterowania elementów
vector() tworzy pusty wektor
vector(size_type n) tworzy wektor n-wymiarowy
vector(size_type n, const T& t) tworzy wektor z n kopii obiektu t
iterator begin() zwraca iterator wskazujÄ…cy na poczÄ…tek
iterator end() zwraca iterator wskazujÄ…cy na koniec
reference front() zwraca pierwszy element
reference back() zwraca ostatni element
size_type size() const zwraca rozmiar wektora
size_type capacity() const ile zarezerwowanej pamięci (elementów)
reference operator[](size_type n) zwraca n ty element
void reserve(size_t n) zapewnia n elementów wektora
void resize(n, t = T()) dodaje bądz usuwa by było n elementów
void push_back(const T&) wstawia element na koniec
void pop_back() usuwa ostatni element
iterator erase(iterator pos) usuwa wskazany element
Programowanie Obiektowe 136
Iteratory
Ć" Uogólnienie wskazników.
Ć" Główny cel  sprawne poruszanie się po strukturach danych.
Ć" Przykład: wskazniki istotnie szybciej pozwalają przebiec przez wszystkie
elementy tablicy niż iterowanie zmiennej całkowitej i dostęp do danych
przez operator[]:
1 const int n = 100000;
2 int tab[n];
3 // nieoptymalnie
4 for (int i=0; i5 tab[i] = i; // to samo co "(tab+i) = i;
6 // optymalnie
7 for (int i = n, "p=tab+n; p--; )
8 "p = --i;
Programowanie Obiektowe 137
Ć" Podejście naiwne:
1 template
2 class Vector
3 {
4 protected:
5 T"data;
6 int size;
7 public:
8 Vector(int s) {data=new T[size=s]; }
9 ~Vector() {delete[] data;}
10 T &operator[] (int i) {return data[i];}
11 int Size() {return size;}
12 };
13 ...
14 Vector w;
15 ...
16 for (int i=0; i17 w[i] = i;
Programowanie Obiektowe 138
Ć" Podejście z niepoprawnym iteratorem (wolniej niż naiwnie):
1 template
2 class Vector {
3 // ...
4 class Iterator {
5 T"ptr;
6 public:
7 Iterator(T"p) {ptr = p;}
8 T &operator"() {return"ptr;}
9 void operator ++() {ptr++;}
10 int operator <(const Iterator &i) {return ptr11 };
12 Iterator begin() {return Iterator(data);}
13 Iterator end() {return Iterator(data+size);}
14 };
15 ...
16 Vector::Iterator it=w.begin(), e=w.end();
17 for (int i=0; it18 "it = i++;
Programowanie Obiektowe 139
Ć" Podejście z poprawnym iteratorem:
1 template
2 class Vector
3 {
4 protected:
5 T"data;
6 int size;
7 public:
8 Vector(int s) {data=new T[size=s]; }
9 ~Vector() {delete[] data;}
10
11 typedef T"Iterator;
12 Iterator begin() {return data;}
13 Iterator end() {return data+size;}
14 };
15 ...
16 Vector::Iterator it=w.begin(), e=w.end();
17 for (int i=0; it18 "it = i++;
Programowanie Obiektowe 140
deque
Ć" Przykład:
1 deque Q;
2 Q.push_back(3);
3 Q.push_front(1);
4 Q.insert(Q.begin() + 1, 2);
5 Q[2] = 0;
6 copy(Q.begin(), Q.end(), ostream_iterator(cout, " "));
7 // Na wyjściu dostaniemy: 1 2 0
Ć" Parametry:
T  typ elementów
Alloc  alokator pamięci
Programowanie Obiektowe 141
Ć" Niemal to samo co vector, ale dodaje i usuwa pierwszy element w stałym
czasie.
Ć" Nie posiada metod capacity() i reserve().
Ć" Dodatkowe składowe:
void push_front(const T&) wstawia element na poczÄ…tek
void pop_front() usuwa pierwszy element
Programowanie Obiektowe 142
list
Ć" Lista dwukierunkowa
Ć" Przykład:
1 list L;
2 L.push_back(0);
3 L.push_front(1);
4 L.insert(++L.begin(), 2);
5 copy(L.begin(), L.end(), ostream_iterator(cout, " "));
6 // Na wyjściu dostajemy: 1 2 0
Ć" Parametry:
T  typ elementów listy
Alloc  alokator pamięci
Programowanie Obiektowe 143
Ć" Wybrane składowe:
reference typ: referencja na T
pointer typ: wskaznik na T
iterator typ do iterowania elementów
list() tworzy pustÄ… listÄ™
list(size_type n) tworzy listę n elementów T()
list(size_type n, const T& t) tworzy wektor z n kopii obiektu t
iterator begin() zwraca iterator wskazujÄ…cy na poczÄ…tek
iterator end() zwraca iterator wskazujÄ…cy na koniec
reference front() zwraca pierwszy element
reference back() zwraca ostatni element
size_type size() const zwraca rozmiar wektora
reference operator[](size_type n) zwraca n ty element
void reverse() odwraca kolejność elementów
void push_back(const T&) wstawia element na koniec
void remove(const T& value) usuwa elementy równe value
void merge(list& L) Å‚Ä…czy uporzÄ…dkowane listy
void sort() sortuje (stabilnie, złożoność nlogn)
Programowanie Obiektowe 144
slist
Ć" Lista jednokierunkowa
Ć" Przykład:
1 slist L;
2 L.push_front(0);
3 L.push_front(1);
4 L.insert_after(L.begin(), 2);
5 copy(L.begin(), L.end(), // Na wyjściu 1 2 0
6 ostream_iterator(cout, " "));
7 cout << endl;
8
9 slist::iterator back = L.previous(L.end());
10 back = L.insert_after(back, 3);
11 back = L.insert_after(back, 4);
12 back = L.insert_after(back, 5);
13 copy(L.begin(), L.end(), // Na wyjściu: 1 2 0 3 4 5
14 ostream_iterator(cout, " "));
15 cout << endl;
Programowanie Obiektowe 145
Ć" Mniej zajętej pamięci niż w list
Ć" Większa złożoność pewnych operacji np insert() i erase()
Ć" Lista metod niemal identyczna z list
Programowanie Obiektowe 146
set
Ć" Implementacja zbioru reprezentowanego w sposób uporządkowany dla
sprawniejszej obsługi, wstawianie jednego (uporządkowanego) zbioru do
drugiego jest bardzo szybkie itp.
Ć" Prosty kontener asocjacyjny  klucze i wartości (tutaj tożsame)
Ć" Parametry:
Key  typ elementów zbioru (kluczy i wartości)
Compare  funkcja porównująca zdefiniowana jako klasa
Alloc  alokator pamięci
Ć" Przykład:
1 struct ltstr
2 {
3 bool operator()(const char"s1, const char"s2) const
4 {
5 return strcmp(s1, s2) < 0;
6 }
7 };
8
Programowanie Obiektowe 147
9 int main()
10 {
11 const int N = 6;
12 const char"a[N] = {"isomer", "ephemeral", "prosaic",
13 "nugatory", "artichoke", "serif"};
14 const char"b[N] = {"flat", "this", "artichoke",
15 "frigate", "prosaic", "isomer"};
16
17 set A(a, a + N);
18 set B(b, b + N);
19 set C;
20
21 cout << "Set A: ";
22 copy(A.begin(), A.end(), ostream_iterator(cout, " "));
23 cout << endl;
24 cout << "Set B: ";
25 copy(B.begin(), B.end(), ostream_iterator(cout, " "));
26 cout << endl;
27
Programowanie Obiektowe 148
28 cout << "Union: ";
29 set_union(A.begin(), A.end(), B.begin(), B.end(),
30 ostream_iterator(cout, " "),
31 ltstr());
32 cout << endl;
33
34 cout << "Intersection: ";
35 set_intersection(A.begin(), A.end(), B.begin(), B.end(),
36 ostream_iterator(cout, " "),
37 ltstr());
38 cout << endl;
39
40 set_difference(A.begin(), A.end(), B.begin(), B.end(),
41 inserter(C, C.begin()),
42 ltstr());
43 cout << "Set C (difference of A and B): ";
44 copy(C.begin(), C.end(), ostream_iterator(cout, " "));
45 cout << endl;
46 }
Programowanie Obiektowe 149
multiset
Ć" Podobnie jak w set, ale z możliwymi powtórzeniami elementów
Ć" Przykład:
1 int main()
2 {
3 const int N = 10;
4 int a[N] = {4, 1, 1, 1, 1, 1, 0, 5, 1, 0};
5 int b[N] = {4, 4, 2, 4, 2, 4, 0, 1, 5, 5};
6
7 multiset A(a, a + N);
8 multiset B(b, b + N);
9 multiset C;
10
11 cout << "Set A: ";
12 copy(A.begin(), A.end(), ostream_iterator(cout, " "));
13 cout << endl;
14 cout << "Set B: ";
15 copy(B.begin(), B.end(), ostream_iterator(cout, " "));
Programowanie Obiektowe 150
16 cout << endl;
17
18 cout << "Union: ";
19 set_union(A.begin(), A.end(), B.begin(), B.end(),
20 ostream_iterator(cout, " "));
21 cout << endl;
22
23 cout << "Intersection: ";
24 set_intersection(A.begin(), A.end(), B.begin(), B.end(),
25 ostream_iterator(cout, " "));
26 cout << endl;
27
28 set_difference(A.begin(), A.end(), B.begin(), B.end(),
29 inserter(C, C.begin()));
30 cout << "Set C (difference of A and B): ";
31 copy(C.begin(), C.end(), ostream_iterator(cout, " "));
32 cout << endl;
33 }
Programowanie Obiektowe 151
map
Ć" Posortowany kontener asocjacyjny przypisujący obiektom typu Key
(kluczom) obiekty typu Data (wartości).
Ć" Kontener par pair.
Ć" Klucze muszą być unikalne.
Ć" Parametry:
Key  typ kluczy
Data  typ wartości
Compare  funkcja porównująca klucze
Alloc  alokator pamięci
Ć" Przykład:
1 struct ltstr
2 {
3 bool operator()(const char"s1, const char"s2) const
4 {
5 return strcmp(s1, s2) < 0;
6 }
7 };
Programowanie Obiektowe 152
8
9 int main()
10 {
11 map months;
12
13 months["january"] = 31;
14 months["february"] = 28;
15 months["march"] = 31;
16 months["april"] = 30;
17 months["may"] = 31;
18 months["june"] = 30;
19 months["july"] = 31;
20 months["august"] = 31;
21 months["september"] = 30;
22 months["october"] = 31;
23 months["november"] = 30;
24 months["december"] = 31;
25
26 cout << "june -> " << months["june"] << endl;
Programowanie Obiektowe 153
27 map::iterator cur = months.find("june");
28 map::iterator prev = cur;
29 map::iterator next = cur;
30 ++next;
31 --prev;
32 cout << "Previous (in alphabetical order) is "
33 << ("prev).first << endl;
34 cout << "Next (in alphabetical order) is "
35 << ("next).first << endl;
36 }
Programowanie Obiektowe 154
multimap
Ć" Podobnie jak w map, ale z możliwymi powtórzeniami kluczy
Ć" Przykład:
1 struct ltstr
2 {
3 bool operator()(const char"s1, const char"s2) const
4 {
5 return strcmp(s1, s2) < 0;
6 }
7 };
8
9 int main()
10 {
11 multimap m;
12
13 m.insert(pair("a", 1));
14 m.insert(pair("c", 2));
15 m.insert(pair("b", 3));
Programowanie Obiektowe 155
16 m.insert(pair("b", 4));
17 m.insert(pair("a", 5));
18 m.insert(pair("b", 6));
19
20 cout << "Number of elements with key a: " << m.count("a") << endl;
21 cout << "Number of elements with key b: " << m.count("b") << endl;
22 cout << "Number of elements with key c: " << m.count("c") << endl;
23
24 cout << "Elements in m: " << endl;
25 for (multimap::iterator it = m.begin();
26 it != m.end();
27 ++it)
28 cout << " [" << ("it).first << ", " << ("it).second << "]" << endl;
29 }
Programowanie Obiektowe 156
Platforma .NET
Ć" .NET Framework = Common Language Runtime (CLR) + Framework
Class Library (FCL)
Ć" Środowisko a kompilatory
Ć" MSIL - MicroSoft Intermediate Language (Common Intermediate
Language - CIL)
î% wspólny kod wyjÅ›ciowy dla różnych jezyków programowania (Visual
Basic, C#, Managed C++, JScript. . . )
î% każdy program można Å‚atwo zdekompilować
î% programy utrudniajÄ…ce dekompilacjÄ™ - obfuscators
Ć" JIT (Just in Time) compiler
î% tworzy kod maszynowy dla danego procesora (jak w Javie)
î% optymalizacja na dany komputer  bardzo poważna zaleta
Programowanie Obiektowe 157
Platforma .NET  c.d.
Ć" Zarządzanie bibliotekami dynamicznymi
î% Zestaw (assembly) jako uogólnienie DLL
î% Zezwolenie na wiele wersji tego samego zestawu
Ć" bogactwo biblioteki standardowej .NET (FCL)  przestrzenie nazw
nabierają jeszcze większego znaczenia
Ć" projekt MONO http://www.mono-project.com/ - .NET na Unix ach
Programowanie Obiektowe 158
Język C#  podstawy
Ć" Brak plików nagłówkowych, bardzo szybka kompilacja
Ć" Wszystko wewnątrz klas
Ć" Identyfikatory to ciągi znaków Unicode (mogą zawierać polskie znaki)
Ć" Operator . zamiast ::
Ć" Pierwszy program
1 class Example
2 {
3 public static void Main () {
4 System.Console.WriteLine ("Hello world!");
5 }
6 }
Ć" Dostęp definiowany przy każdej składowej
Ć" Średniki po deklaracjach klas niepotrzebne
Programowanie Obiektowe 159
Przestrzenie nazw
Ć" Deklaracje dokładania do przestrzeni i korzystanie z przestrzeni
1 namespace Poczatki {
2 using System;
3 class Example {
4 public static void Main () {
5 Console.WriteLine ("Hello world!");
6 }
7 }
8 }
Ć" Można zagnieżdżać przestrzenie nazw tworząc hierarchię
Ć" Przykłady z hierarchii FCL
1 System.IO
2 System.Collections.Generic
3 System.Runtime.Serialization.Formatters.Binary
4 System.Security.Cryptography
Programowanie Obiektowe 160
Typy wartościowe i referencyjne
Ć" Stos i sterta (stack and heap)
î% stos  obsÅ‚uga wywoÅ‚aÅ„ funkcji i zmiennych lokalnych
î% sterta  miejsce na dynamicznie alokowane zmienne
î% czyszczenie stosu zwiÄ…zane z powrotami z funkcji
î% czyszczenie sterty przejmuje system zbierania odpadków (garbage
collection)
Ć" Typy wartościowe (typy proste, struct, enum)
1 class Test {
2 static void Main () {
3 int x = 3;
4 int y = x; // assign x to y, y is now a copy of x
5 x++; // increment x to 4
6 System.Console.WriteLine (y); // prints 3
7 }
8 }
Programowanie Obiektowe 161
Ć" Typy referencyjne (klasy, kolekcje, delegacje, interfejsy)
î% wartość i adres jej przechowywania w jednym
î% analogicznie do przekazywania parametrów przez referencjÄ™ w C++
î% syntaktycznie jak wartoÅ›ci, semantycznie jak wskazniki
1 using System;
2 using System.Text;
3 class Test {
4 static void Main () {
5 StringBuilder x = new StringBuilder ("hello");
6 StringBuilder y = x;
7 x.Append (" there");
8 Console.WriteLine (y); // prints "hello there"
9 }
10 }
Programowanie Obiektowe 162
Ć" typy wartościowe i referencyjne - przykład porównujący
1 class PointR { // typ referencyjny
2 public int x, y;
3 }
4 struct PointV { // typ wartościowy
5 public int x, y;
6 }
7 class Test {
8 static void Main() {
9 PointR a; // 4 bajty na stosie
10 PointV b; // 8 bajtów na stosie
11 a = new PointR(); // alokacja 8 bajtów na stercie
12 b = new PointV(); // zawołanie konstruktora
13 a.x = 7;
14 b.x = 7;
15 }
16 }
Programowanie Obiektowe 163
Ć" opakowywanie wartości w obiekty referencyjne i rozpakowywanie (boxing,
unboxing)
1 class Test {
2 static void Main () {
3 int x = 9;
4 object o = x; // box the int
5 int y = (int)o; // unbox the int
6 }
7 }
Programowanie Obiektowe 164
Predefiniowane typy wartościowe
Ć" typy całkowite
alias typ rozmiar znak
sbyte System.SByte 1 tak
short System.Int16 2 tak
int System.Int32 4 tak
long System.Int64 8 tak
byte System.Byte 1 nie
ushort System.UInt16 2 nie
uint System.UInt32 4 nie
ulong System.UInt64 8 nie
1 int ii = 5;
2 uint ui = 5U;
3 long ll = 5L;
4 ulong ul = 5UL;
Programowanie Obiektowe 165
Ć" typy rzeczywiste
alias typ rozmiar
float System.Single 4
double System.Double 8
decimal System.Decimal 16
1 float f = 3.14f;
2 double d = 3.14;
3 decimal m = 123456789.123456789m;
typ decimal:
î% 28-29 cyfr znaczÄ…cych, ale maÅ‚y zakres
î% szczególnie przydatny w finansach
Ć" char i bool
alias typ rozmiar
char System.Char 2
bool System.Boolean 1/2
Programowanie Obiektowe 166
Predefiniowane typy referencyjne
alias typ rozmiar
object System.Object 0/8
string System.String min. 20
Ć" object  klasa bazowa dla wszystkich typów, dla referencyjnych 8 bajtów
Ć" string  niezmienna sekwencja znaków Unicode
Ć" string  zwykła klasa o specjalnym traktowaniu
1 string a1 = "\\\\server\\fileshare\\helloworld.cs";
2 string a2 = @"\\server\fileshare\helloworld.cs";
3 Console.WriteLine(a1==a2); // Prints "True"
4 string b1 = "First Line\r\nSecond Line";
5 string b2 = @"First Line
6 Second Line";
7 Console.WriteLine(b1==b2); // Prints "True"
Programowanie Obiektowe 167
Garbage collection
Ć" new - alokacja jak w C++
Ć" nie zwalniamy pamięci wprost (na wzór delete z C++)
Ć" garbage collection system  system zarządzania pamięcią
î% zarzÄ…dza wszelkimi referencjami do obiektów
î% odzyskuje pamięć po niepotrzebnych obiektach
î% Uwaga! ważne zerowanie  dÅ‚ugo żyjÄ…cych referencji, bo inaczej
wycieki pamięci
î% Uwaga! obiekty mogÄ… zmieniać swoje poÅ‚ożenie (adres) bez wiedzy
programisty
1 public void Test()
2 {
3 Macierz m = new Macierz();
4 m = null; // dla zmiennych lokalnych niepotrzebne
5 }
Programowanie Obiektowe 168
Garbage collection
1 // W klasie Macierz
2 public Macierz(Manager mgr)
3 {
4 mgr.Rejestruj(this); // mgr wrzuca this do kolekcji
5 ...
6 }
7 public void Test(Manager mgr)
8 {
9 Macierz m = new Macierz(mgr);
10 ...
11 // m nie będzie zwolniona, bo "trzyma" ją mgr
12 }
Programowanie Obiektowe 169
Typ wyliczeniowy
Ć" Standardowo wartości 0, 1, 2, . . .
1 enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};
Ć" Wartości 1, 2, . . .
1 enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
Ć" Wartości jawnie zadane i typ long:
1 enum Range : long {Max = 2147483648L, Min = 255L};
Ć" Brak konwersji niejawnych - trzeba jawnie
1 int i = (int)Days.Sun;
2 long l = (long)Range.Max;
Ć" Dostępne operatory: == != < > <= >= + - ^ & | ~ = += -= ++ --
sizeof
Programowanie Obiektowe 170
Tablice
Ć" System.Array  zwykła klasa o specjalnym traktowaniu
Ć" syntaktyka podobna do C++, ale z pewnymi różnicami
Ć" tablice prostokątne i  postrzępione (jagged)
1 int[] tab, tab2 = new int[15];
2 int[,] tab2d = new int[5,5];
3 double[][] macierz = new double[5][];
4 for (int i=0; i<5; i++)
5 macierz[i] = new int[10+i];
6 tab2[5] = tab2d[0,3] = 7;
7 macierz[0][3] = 7;
8 int[,] zainicjowana = {{1,2},{3,4}};
Ć" kontrola zakresów, wyjątek IndexOutOfRangeException, dzięki
optymalizacji nie musi dużo kosztować
Programowanie Obiektowe 171
Wybrane metody i własności klasy Array
Length długość tablicy
Rank liczba wymiarów
IsReadOnly czy tylko do odczytu
GetLength() długość w danym wymiarze
GetLowerBound() dolne ograniczenie danego wymiaru
GetUpperBound() górne ograniczenie danego wymiaru
Sort() sortowanie tablic jednowymiarowych
Reverse() odwracanie kolejności tablic jednowymiarowych
IndexOf() indeks pierwszego wystąpienia wartości
LastIndexOf() indeks ostatniego wystąpienia wartości
Copy() kopiowanie fragmentu
Clear() ustawianie wartości 0 lub null
Programowanie Obiektowe 172
Zmienne
Ć" ściśle określony typ (operacje, które można wykonywać)
Ć" każda zmienna musi być zainicjowana przed użyciem
Ć" wartości domyślne dla pól obiektów złożonych
î% numeryczne i wyliczeniowe  0
î% char   \0
î% bool  false
î% referencyjne  null
Programowanie Obiektowe 173
Przekazywanie argumentów do metod
Ć" domyślnie przez wartość (działania na kopii)
Ć" w przypadku typów referencyjnych  kopia referencji
Ć" ref  przekazanie przez referencję
1 public void zamień(ref int a, ref int b)
2 {
3 int c = a;
4 a = b;
5 b = c;
6 }
Programowanie Obiektowe 174
Ć" out  parametr traktowany jak wyjście funkcji, kompilator pilnuje by
zmiennej coś przypisać w funkcji
1 public void ustaw(out int a, out int b)
2 {
3 a = 5;
4 b = 7; // skomentuj jedną z linii by dostać błąd
5 }
Programowanie Obiektowe 175
Ć" ref i out konieczne również przy wywołaniach
Ć" zmienna przekazana z modyfikatorem out może nie być zainicjowana
1 public void test()
2 {
3 int x, y;
4 ustaw(out x, out y);
5 zamień(ref x, ref y);
6 }
Ć" nie ma mechanizmu domyślnych wartości parametrów metod, trzeba
jawnie przeciążać metody, by uzyskać ten sam efekt
1 public int Kalkuluj(int a, int b) { return ... }
2 public int Kalkuluj(int a) { return Kalkuluj(a, 0); }
Programowanie Obiektowe 176
Modyfikatory dostępu
Ć" public   pełna widoczność
Ć" private  dostęp tylko dla metod tej samej klasy
Ć" protected  dostęp dla metod tej samej klasy i klas potomnych
Ć" internal  dostęp w ramach zestawu (assembly)
Ć" protected internal  suma logiczna warunków dostępu dla
protected i internal
Ć" domyślnie:
î% dla niezagnieżdżonych klas internal
î% dla skÅ‚adowych klas private
Ć" dziedziczenie zawsze publiczne!
Programowanie Obiektowe 177
Pola klas
Ć" pola mogą być inicjowane w linii deklaracji (przypisanie nastąpi przed
konstruktorem)
1 public class test
2 {
3 internal string kto = "Ala";
4 public string KtoTo() { return kto; }
5 }
Ć" pola statyczne są alokowane i inicjowane dopiero wtedy, gdy są potrzebne
Ć" pola tylko do odczytu
1 readonly int rozmiar = 100;
2 static readonly maxRozmiar = 1000;
î% wyznaczane w trakcie dziaÅ‚ania, nie kompilacji
î% muszÄ… być zainicjowane w linii deklaracji bÄ…dz w konstruktorze
Programowanie Obiektowe 178
Ć" pola stałe
1 public const double PI = 3.14159265358979323846;
î% wyznaczane w trakcie kompilacji
î% statyczne z zaÅ‚ożenia
î% dozwolone typy: sbyte, byte, short, ushort, int, uint, long,
ulong, float, double, decimal, bool, char, string, enum
î% muszÄ… być zainicjowane w linii deklaracji bÄ…dz w konstruktorze
Programowanie Obiektowe 179
Własności (properties)
Ć" implementowane inline
1 public class ProstokÄ…t
2 {
3 int lewa, góra, długość, szerokość;
4 public int Prawa {
5 get { return lewa + dlugość; }
6 set ( lewa = value - dlugość; }
7 }
8 }
Ć" w praktyce para metod get_Prawa() i set_Prawa(int value)
Programowanie Obiektowe 180
Operatory indeksujÄ…ce (indexers)
Ć" definiowane podobnie do własności
1 public class Tab5Double {
2 double[] tab = new double[5];
3 double suma;
4 public double this[int i] {
5 get { return tab[i]; }
6 set { suma += value-tab[i]; tab[i] = value; }
7 }
8 public double Srednia {
9 get { return suma / 5; }
10 }
11 }
Ć" można zdefiniować wiele operatorów o różnych listach argumentów
Programowanie Obiektowe 181
Konstruktory klas
Ć" jak w C++ tj. metody o nazwie klasy
1 public class TabDouble {
2 double[] tab;
3 TabDouble(int n) { tab = new double[n]; }
4 TabDouble() : this(n) {};
5 }
Ć" pola inicjowane w linii deklaracji przychodzą do konstruktora już
zainicjowane (w kolejności występowania w klasie)
Ć" mogą być opatrzone dowolnym modyfikatorem dostępu
Programowanie Obiektowe 182
Konstruktor statyczny
Ć" może być tylko jeden w klasie
Ć" wołany przed stworzeniem pierwszego obiektu i przed dostępem do
jakiegokolwiek pola statycznego klasy
1 public class TabDouble {
2 static TabManager tabmgr;
3 static TabDouble() { tabmgr = new TabManager(); }
4 }
Ć" pola statyczne inicjalizowane przed konstruktorem statycznym
Ć" kolejność wołania konstruktorów statycznych jest nieustalona, również
dziedziczenie nie ma tu znaczenia
Programowanie Obiektowe 183
Destruktor
Ć" Jak w C++ metoda o nazwie klasy poprzedzonej tyldą
Ć" Zadania całkiem inne niż w C++ ze względu na garbage collection
Ć" Bardzo rzadko potrzebne
Ć" Czas wykonania destruktora jest nieokreślony
Ć" Kompilowany do funkcji wirtualnej Finalize()
1 protected override void Finalize() {
2 ...
3 base.Finalize();
4 }
Programowanie Obiektowe 184
Dziedziczenie
Ć" Klasa bez jawnego dziedziczenia dziedziczy po object
Ć" Wielokrotne dziedziczenie jest niedozwolone
Ć" Prosty przykład:
1 public class Kwadrat : ProstokÄ…t {
2 public Kwadrat(int lewa, int góra, int bok)
3 : base(lewa, góra, bok, bok)
4 {
5 }
6 public OkrÄ…g OkrÄ…gWpisany();
7 }
Programowanie Obiektowe 185
Ć" Konwersje niejawne dozwolone tylko w stronę bazowej
1 Kwadrat k = new Kwadrat(0, 0, 5);
2 ProstokÄ…t p = k; // OK
3 Kwadrat w = (Kwadrat)p; // jawna konwersja konieczna
Ć" Nieudana jawna konwersja oznacza wyjątek InvalidCastException
Ć" Operator as (w wyniku null, gdy się nie uda)
1 Kwadrat w = p as Kwadrat;
Ć" Operator is (pytanie o dziedziczenie lub implementację interfejsu)
1 if (p is Kwadrat)
2 ((Kwadrat)p).OkragWpisany().Rysuj();
Programowanie Obiektowe 186
Polimorfizm
Ć" Polimorfizm to możliwość realizacji tego samego wywołania w kontekście
wielu typów.
Ć" Dziedziczenie klas i implementowanie interfejsów
Ć" Metody wirtualne
1 public class Figura {
2 public virtual void Rysuj() {throw new NotDefined();}
3 }
4 public class ProstokÄ…t : Figura {
5 public override void Rysuj() {...}
6 }
7 public class Kwadrat : ProstokÄ…t {
8 public override void Rysuj() {...}
9 }
Programowanie Obiektowe 187
Klasy abstrakcyjne
Ć" Klasy abstrakcyjne mogą zawierać metody abstrakcyjne
Ć" Metody abstrakcyjne to metody wirtualne bez implementacji:
1 public abstract class Figura {
2 public abstract void Rysuj();
3 }
Ć" W C++
1 class Figura {
2 public:
3 virtual void Rysuj() = 0;
4 }
Programowanie Obiektowe 188
Ć" Ukrywanie metod wirtualnych  przerywanie wirtualności
1 public class Figura {
2 public virtual void Rysuj() {throw new NotDefined();}
3 }
4 public class ProstokÄ…t : Figura {
5 public override void Rysuj() {...}
6 }
7 public class Kwadrat : ProstokÄ…t {
8 public new void Rysuj() {...}
9 }
Wówczas:
1 Kwadrat k = new Kwadrat(0, 0, 5);
2 k.Rysuj(); // woła Kwadrat.Rysuj()
3 ((Figura)k).Rysuj(); // woła Prostokąt.Rysuj()
Programowanie Obiektowe 189
Ć" Modyfikator sealed  klasy i metody  zalakowane
î% Nie można dziedziczyć po zalakowanej klasie
1 public sealed class ProstokÄ…t : Figura {
2 ...
3 }
4 public class Kwadrat : ProstokÄ…t { // BÅ‚Ä…d!
5 ...
6 }
î% Pozwala kompilatorowi zmienić wywoÅ‚ania wirtualne na niewirtualne
î% Zwykle dla klas zawierajÄ…cych tylko statyczne metody (np. Math)
î% Można zalakować pojedyÅ„cze metody
1 public class ProstokÄ…t : Figura {
2 public sealed override Rysuj() {...}
3 }
Programowanie Obiektowe 190
SÅ‚owo kluczowe base
Ć" Daje dostęp do metod klasy bazowej
Ć" Podobne w użyciu jak słowo kluczowe this:
1 public class ProstokÄ…t : Figura {
2 public Prostokąt(int x, int y, int dług, int szer) {...}
3 public override void Rysuj() {...}
4 }
5 public class Kwadrat : ProstokÄ…t {
6 public Kwadrat(int x, int y, int bok)
7 : base(x, y, bok, bok) {...}
8 public Kwadrat(int bok)
9 : this(0, 0, bok) {...}
10 public override void Rysuj() {
11 base.Rysuj(); ...
12 }
13 }
Programowanie Obiektowe 191
Interfejsy
Ć" Interfejsy to specyfikacje możliwości klas (główne narzędzie polimorfizmu
w C#)
Ć" Klasy i struktury mogą implementować interfejsy tzn. implementować
wszystko co wyspecyfikowane w ramach interfejsu
Ć" Konstrukcje podobne do klas z kilkoma bardzo istotnymi różnicami:
î% Interfejsy nie zawierajÄ… implementacji żadnych metod (sÄ… trochÄ™ jak
klasy abstrakcyjne zawierające wyłącznie deklaracje abstrakcyjnych
metod)
î% Klasy i struktury mogÄ… implementować wiele interfejsów
î% Struktury mogÄ… implementować interfejsy, ale nie mogÄ… dziedziczyć klas
Ć" Interfejsy mogą zawierać deklaracje:
î% metod,
î% wÅ‚asnoÅ›ci,
î% operatorów indeksujÄ…cych,
î% zdarzeÅ„.
Programowanie Obiektowe 192
Ć" Definicja interfejsu
1 public interface ICloneable {
2 object Clone();
3 }
Ć" Interfejs może rozszerzać inne interfejsy:
1 public interface ITablica {
2 object this[int i] { get; set; }
3 }
4 public interface ISortowalnaTablica : ITablica {
5 void Sortuj();
6 }
Programowanie Obiektowe 193
Ć" Implementacja interfejsu
1 public class TablicaInt : ISortowalnaTablica {
2 public object this[int i] { get { return 0;} set {} }
3 public void Sortuj() { }
4 }
Ć" Implementacja interfejsu w sposób jawny (np. żeby uniknąć konfliktu, gdy
dwa interfejsy zawierają taką samą składową)
1 public class TablicaCalkowitych : ISortowalnaTablica {
2 object ITablica.this[int i] { get {return 1;} set {} }
3 void ISortowalnaTablica.Sortuj() { }
4 }
Ć" Dziedziczenie i implementacja  najpierw klasa, potem interfejsy
1 public class Kwadrat : ProstokÄ…t, ICloneable {
2 ...
3 }
Programowanie Obiektowe 194
Reimplementacja interfejsu
Ć" Jeśli klasa bazowa implementuje składową interfejsu jako wirtualną, to
klasy potomne mogą je dociążać:
1 public class Bazowa : ICloneable {
2 public virtual object Clone() {return new Bazowa();}
3 }
4 public class Potomna : Bazowa {
5 public override object Clone() {return new Potomna();}
6 }
Ć" Uwaga na virtual/override!
Ć" Jeśli w powyższym Clone zabraknie virtual/override, to:
1 Potomna coÅ› = new Potomna();
2 (coś as ICloneable).Clone(); // woła Bazowa.Clone()
Programowanie Obiektowe 195
Ć" Można też reimplementować interfejs:
1 public class Bazowa : ICloneable {
2 public object Clone() {return new Bazowa();}
3 }
4 public class Potomna : Bazowa, ICloneable {
5 public object Clone() {return new Potomna();}
6 }
Wówczas:
1 Potomna coÅ› = new Potomna();
2 (coś as ICloneable).Clone(); // woła Potomna.Clone()
Programowanie Obiektowe 196
Delegaty
Ć" Sygnatury metod  typy do przechowywania i wołania metod
(pojedyńczych bądz list metod) o określonej liście parametrów
1 delegate Figura Transformacja(Figura f);
2 class KolekcjaFigur {
3 Figura[] figury;
4 KolekcjaFigur Transformuj(Transformacja t)
5 {
6 KolekcjaFigur kf = new KolekcjaFigur(liczbaFigur);
7 foreach (Figura f in Figury)
8 kf.Dodaj(t(f));
9 return kf;
10 }
11 }
Programowanie Obiektowe 197
Ć" Argumenty mogą być specyfikowane z modyfikatorem params
1 delegate int Kombinacja(params int[] arg);
2 class Operacje
3 {
4 static public int Suma(params int[] argumenty) {
5 int wynik = 0;
6 foreach (int i in argumenty)
7 wynik += i;
8 return wynik;
9 }
10 static public void Main() {
11 Kombinacja k = new Kombinacja(Suma);
12 System.Console.WriteLine("Wynik = {0}", k(1, 2, 3, 4));
13 }
14 }
Programowanie Obiektowe 198
Ć" Operatory += i -= do obsługi delegatów przechowujących listy metod
1 delegate int Kombinacja(params int[] arg);
2 class Operacje
3 {
4 static public int Suma(params int[] argumenty) { ... }
5 static public int Iloczyn(params int[] argumenty) { ... }
6 static public void Main() {
7 Kombinacja k = new Kombinacja(Suma);
8 k += Iloczyn;
9 //k -= Suma;
10 System.Console.WriteLine("Wynik = {0}", k(1, 2, 3, 4));
11 }
12 }
î% Kolejność woÅ‚ania taka jak kolejność dodawania.
î% Delegat zwraca wynik ostatniej metody z listy.
Programowanie Obiektowe 199
Zdarzenia
Ć" Interfejsy graficzne sterowane zdarzeniami.
Ć" Delegaty  doskonały środek do realizacji obsługi zdarzeń.
Ć" Konwencja: pierwszy argument to zródło, drugi to parametry zdarzenia
(dziedziczy po System.EventArgs):
1 delegate void MoveEventHandler(object source,
2 MoveEventArgs e);
Ć" Przykład parametrów zdarzenia:
1 public class MoveEventArgs : EventArgs {
2 public int newPosition;
3 public bool cancel;
4 public MoveEventArgs(int newPosition) {
5 this.newPosition = newPosition;
6 }
7 }
Programowanie Obiektowe 200
Ć" Przykład uruchomienia zdarzenia:
1 class Slider {
2 int position;
3 public event MoveEventHandler Move;
4 public int Position {
5 get { return position; }
6 set {
7 if (Move != null) { // if invocation list not empty
8 MoveEventArgs args = new MoveEventArgs(value);
9 Move(this, args); // fire event
10 if (args.cancel) return;
11 }
12 position = value;
13 }
14 }
15 }
Programowanie Obiektowe 201
Zestawy (ang. assembly)
Ć" Nowe podejście do bibliotek alokowanych dynamicznie.
Ć" Różne wersje tej samej biblioteki mogą równolegle funkcjonować w
systemie.
Ć" Zestaw może stanowić pojedynczy moduł (plik .dll lub .exe), albo kilka
modułów (słabe wsparcie).
Ć" Nie mylić z przestrzeniami nazw (ang. namespaces), choć często ta sama
nazwa jest użyta i dla zestawu i przestrzeni nazw.
Ć" Silne nazwy (strong names)  unikalne, generowane przy użyciu klucza
prywatnego
Ć" Global Assembly Cache  magazyn zestawów
Programowanie Obiektowe 202
Application domains
Ć" Proces = uruchomiona aplikacja.
Ć" System chroni procesy przed innymi procesami.
Ć" Domeny pozwalają na podobną ochronę w ramach jednego procesu.
Ć" Proces startuje z jedną domyślną domeną, dodatkowe można tworzyć
samemu w miarÄ™ potrzeby.
Ć" Wymiana danych pomiędzy domenami na tych samych zasadach co
między procesami.
Ć" Wiele wątków może biec w ramach jednej domeny.
Ć" Jeden wątek może pracować w ramach różnych domen (ale nie
jednocześnie).
Programowanie Obiektowe 203
Ć" Głowne składowe klasy AppDomain:
î% CurrentDomain  statyczna wÅ‚asność, zwraca bieżącÄ… domenÄ™ dla
bieżącego wątku
î% CreateDomain()  tworzy nowÄ… domenÄ™
î% GetCurrentThreadID()  identyfikator bieżącego wÄ…tku
î% Load() Å‚aduje zestaw do domeny
î% Unload()  usuwa zadanÄ… domenÄ™
î% CreateInstance()  tworzy obiekt w domenie
Programowanie Obiektowe 204
Ć" Przykład:
1 AppDomain ad2 =
2 AppDomain.CreateDomain("Shape Domain");
3 ObjectHandle oh = ad2.CreateInstance(
4 "ProgCSharp", // the assembly name
5 "ProgCSharp.Shape", // the type name with namespace
6 false, // ignore case
7 System.Reflection.BindingFlags.CreateInstance, // flag
8 null, // binder
9 new object[] {3, 5}, // args
10 null, // culture
11 null, // activation attributes
12 null ); // security attributes
Programowanie Obiektowe 205
Atrybuty
Ć" Służą do opisywania elementów składniowych: zestaw, klasa, konstruktor,
delegat, typ wyliczeniowy, zdarzenie, pole, interfejs, metoda, moduł,
parametr, własność, wartość zwracana, struktura
Ć" Meta-dane o klasach, polach itd.
Ć" Przykłady:
1 [assembly: AssemblyKeyFile("c:\\myStrongName.key")]
2 [NoIDispatch]
3 public interface IEksperymentCOM {...}
4 [Serializable]
5 class MySerializableClass { ...}
Ć" Wstawia się je bezpośrednio przed deklaracją, której dotyczą, z wyjątkiem
tych dotyczących zestawów i modułów.
Ć" Atrybuty wewnętrzne  wsparcie Common Language Runtime,
zintegrowane z .NET
Programowanie Obiektowe 206
Ć" Atrybuty użytkownika  klasy dziedziczące po System.Attribute
1 public class MachineAttribute : Attribute
2 {
3 public string name;
4 public Type configType;
5 public MachineAttribute(string name, Type configType)
6 {
7 this.name = name;
8 this.configType = configType;
9 }
10 }
11
12 [Machine("Decision tree", typeof(DTConfig))]
13 public class DT : DTClassifier, IMachine
14 { ... }
Programowanie Obiektowe 207
Ć" Konwencja wspierana przez kompilator: nazwy klas kończą się na
Attribute
Ć" Koniecznie przynajmniej jeden konstruktor.
Ć" Parametry pozycyjne (argumenty konstruktora)
Ć" Parametry nazwane (własności)
1 [Machine("Decision tree", typeof(DTConfig),
2 Description="A standard greedy search decision tree")]
Ć" Atrybut atrybutów (meta-atrybut)
1 [AttributeUsage(AttributeTargets.Class,
2 AllowMultiple = false)]
3 public class MachineAttribute : Attribute
4 { ... }
Ć" Wiele atrybutów można wymienić w jednym nawiasie kwadratowym:
1 [Serializable, Machine(...)]
Programowanie Obiektowe 208
Mechanizm refleksji (reflection)
Ć" Dostęp do meta-danych.
Ć" Duże możliwości penetrowania hierarchii klas, wnętrz klas itd.
Ć" Klasa Type  meta-dane o typach i ich wnętrznościach
Ć" Pobieranie informacji o typie
1 Type t = zmienna.GetType(); // metoda System.Object
2 Type t = Type.GetType("System.Int32");
3 Type t2 = Type.GetType("MyNamespace.MyType", MyAssembly);
4 Type t3 = typeof(System.Int32);
Programowanie Obiektowe 209
Ć" Przykład penetracji typów:
1 using System;
2 using System.Reflection;
3 class Test {
4 static void Main( ) {
5 DumpTypeInfo((new Object()).GetType( ));
6 DumpTypeInfo(typeof(int));
7 DumpTypeInfo(Type.GetType("System.String"));
8 }
9 static void DumpTypeInfo(Type t) {
10 Console.WriteLine("Type: {0}", t);
11 // Retrieve the list of members in the type
12 MemberInfo[ ] miarr = t.GetMembers( );
13 // Print out details on each of them
14 foreach (MemberInfo mi in miarr)
15 Console.WriteLine(" {0}={1}", mi.MemberType, mi);
16 }
17 }
Programowanie Obiektowe 210
Ć" Inne możliwości mechanizmów refleksji:
î% late binding  Å‚adowanie bibliotek, tworzenie obiektów i woÅ‚anie metod na
etapie działania programu a nie kompilacji  Uwaga! znacznie wolniej!
î% Modyfikacja pól prywatnych.
î% Tworzenie typów na etapie dziaÅ‚ania programu
(System.Reflection.Emit), klasy:
î% AssemblyBuilder  dynamiczne tworzenie zestawów,
î% ModuleBuilder  dynamiczne tworzenie modułów,
î% TypeBuilder  dynamiczne tworzenie typów,
î% ILGenerator  dynamiczne tworzenie kodu MSIL.
Programowanie Obiektowe 211
Serializacja
Ć" Konwersja złożonych hierarchicznych struktur danych do strumieni danych
Ć" Deserializacja  operacja odwrotna
Ć" Przestrzenie nazw System.Runtime.Serialization.*,
System.Xml.Serialization.*.
Ć" Podział zadań: strumienie, obiekty formatujące, obiekty serializowane.
Ć" Jawna serializacja:
1 public void SerializeGraph(string file, object root) {
2 Stream stm = new FileStream(file, FileMode.Create);
3 IFormatter fmt = new BinaryFormatter( );
4 fmt.Serialize(stm, root);
5 stm.Flush( );
6 stm.Close( );
7 }
Programowanie Obiektowe 212
Ć" Jawna deserializacja:
1 public object DeserializeGraph(string file) {
2 Stream stm = new FileStream(file, FileMode.Open);
3 IFormatter fmt = new SoapFormatter( );
4 object o = fmt.Deserialize(stm);
5 stm.Close( );
6 return o;
7 }
Programowanie Obiektowe 213
Ć" Niejawna serializacja
î% gdy serializujemy obiekt zawierajÄ…cy jako pola inne serializowalne obiekty,
1 [Serializable]
2 public sealed class Person {
3 public string Name;
4 public int Age;
5 }
6
7 [Serializable]
8 public sealed class Team {
9 public string Name;
10 public Person[ ] Players;
11 }
î% gdy przekazujemy argumenty metodzie woÅ‚anej w innej domenie aplikacji,
1 public Team MergeTeams(Team teamOne, Team teamTwo) {...}
î% w innych przypadkach zdalnego uruchamiania.
Programowanie Obiektowe 214
Ć" Atrybut Serializable
î% Ustawia odpowiedni bit w meta-danych o typie.
î% Nie jest dziedziczony  klasy potomne muszÄ… redeklarować atrybut.
î% Wszystkie skÅ‚adowe muszÄ… być też serializowalne.
Ć" Atrybut NonSerialized  wyłącza pola z serializacji.
1 [Serializable]
2 public sealed class Person {
3 public string Name;
4 public DateTime DateOfBirth;
5 [NonSerialized] public int Age; // Can be calculated
6 // Rest of class...
7 }
Programowanie Obiektowe 215
Ć" Interfejs IDeserializationCallback  pozwala ustawić po
deserializacji pola wyłączone z serializacji
1 [Serializable]
2 public sealed class Person : IDeserializationCallback {
3 public string Name;
4 public DateTime DateOfBirth;
5 [NonSerialized] public int Age; // Can be calculated
6 public void OnDeserialization(object o) {
7 TimeSpan ts = DateTime.Now - DateOfBirth;
8 Age = ts.Days/365; // Rough age in years
9 }
10 // Rest of class...
11 }
Programowanie Obiektowe 216
Ć" Interfejs ISerializable
î% Pozwala na wiÄ™cej kontroli nad szczegółami serializacji.
î% Potrzeba implementacji konstruktora deserializacyjnego:
1 [Serializable]
2 public sealed class Team : ISerializable {
3 public string Name;
4 public Person[ ] Players;
5 public void GetObjectData(SerializationInfo si,
6 StreamingContext sc) {
7 si.AddValue("IChangedTheFieldName", Name);
8 si.AddValue("Players", Players);
9 }
10 private Team(SerializationInfo si, StreamingContext sc) {
11 Name = si.GetString("IChangedTheFieldName");
12 Players = (Person[ ])si.GetValue("Players",
13 typeof(Person[ ]));
14 }
15 }
Programowanie Obiektowe 217
Strumienie
Ć" Abstrakcyjna klasa Stream i jej pochodne  niskopoziomowy zapis i
odczyt
î% CanRead, CanWrite, CanSeek
î% Read(), Write()  binarny odczyt i zapis
î% metody Seek(), SetLength() i wÅ‚asnoÅ›ci Position, Length
î% BeginRead(), EndRead(), BeginWrite(), EndWrite() 
operacje asynchroniczne
î% Flush(), Close()
Programowanie Obiektowe 218
Ć" Klasy potomne:
î% Microsoft.JScript.COMCharStream
î% Microsoft.WindowsMobile.DirectX.GraphicsStream
î% System.IO.BufferedStream
î% System.IO.Compression.DeflateStream
î% System.IO.Compression.GZipStream
î% System.IO.FileStream
î% System.IO.MemoryStream
î% System.IO.UnmanagedMemoryStream
î% System.Net.Security.AuthenticatedStream
î% System.Net.Sockets.NetworkStream
î% System.Security.Cryptography.CryptoStream
Programowanie Obiektowe 219
Ć" Klasy usprawniające pisanie i czytanie
î% BinaryReader, BinaryWriter,
î% StreamReader, StreamWriter, Encoding,
î% StringReader, StringWriter,
î% TextReader, TextWriter  abstrakcyjne klasy bazowe dla StreamXXX i
StringXXX.
Programowanie Obiektowe 220
Ć" Podstawowe klasy obsługi wejścia/wyjścia
î% Directory  metody statyczne
î% DirectoryInfo  metody w kontekÅ›cie obiektu
î% DriveInfo  metody obsÅ‚ugi napÄ™du
î% File  metody statyczne
î% FileInfo  metody w kontekÅ›cie obiektu
î% FileSystemInfo  klasa abstrakcyjna, bazowa dla FileInfo i DirectoryInfo
î% Path  obsÅ‚uga Å›cieżek (wieloplatformowa)
î% SerialPort  obsÅ‚uga portów szeregowych
î% File, FileInfo, DriveInfo, Path, Directory, DirectoryInfo 
sealed
Programowanie Obiektowe 221
Ć" Podstawowy przykład użycia strumieni:
1 using System.IO;
2 class StreamFun {
3 static void Main() {
4 Stream s = new FileStream("foo.txt", FileMode.Create);
5 s.WriteByte(67);
6 s.WriteByte(35);
7 s.Close();
8 }
9 }
Programowanie Obiektowe 222
Ć" Buforowanie odczytu i zapisu:
1 void Run( )
2 {
3 Stream inStream = File.OpenRead("plik");
4 Stream outStream = File.OpenWrite("plik.kopia");
5 BufferedStream bufIn = new BufferedStream(inStream);
6 BufferedStream bufOut = new BufferedStream(outStream);
7
8 byte[] buffer = new Byte[1024];
9 int bytesRead;
10 while ( (bytesRead = bufIn.Read(buffer, 0, 1024)) > 0 )
11 bufOut.Write(buffer, 0, bytesRead);
12
13 bufOut.Flush( );
14 bufIn.Close( );
15 bufOut.Close( );
16 }
Programowanie Obiektowe 223
Ć" Bardziej zaawansowany przykład użycia strumieni:
1 using System;
2 using System.IO;
3 using System.Security.Cryptography;
4 class EncoderFun {
5 static void Main() {
6 Stream stm = new FileStream("foo.txt",
7 FileMode.Open, FileAccess.Read);
8 ICryptoTransform ict = new ToBase64Transform();
9 CryptoStream cs = new CryptoStream(stm,
10 ict, CryptoStreamMode.Read);
11 TextReader tr = new StreamReader(cs);
12 string s = tr.ReadToEnd();
13 Console.WriteLine(s);
14 }
15 }
Programowanie Obiektowe 224
Ć" Binarny zapis i odczyt:
1 public class Student {
2 public string Name;
3 public int Age;
4 public double GPA; }
5 void SaveToStream(Stream stm, Student s) {
6 BinaryWriter bw = new BinaryWriter(stm);
7 bw.Write(s.Name);
8 bw.Write(s.Age);
9 bw.Write(s.GPA);
10 bw.Flush(); // Ensure the BinaryWriter buffer is empty
11 }
12 void ReadFromStream(Stream stm, Student s) {
13 BinaryReader br = new BinaryReader(stm);
14 s.Name = br.ReadString();
15 s.Age = br.ReadInt32();
16 s.GPA = br.ReadDouble();
17 }
Programowanie Obiektowe 225
Ć" Strumienie tekstowe:
1 void SaveToStream(Stream stm, Student s) {
2 TextWriter tw = new StreamWriter(stm);
3 tw.WriteLine(s.Name);
4 tw.WriteLine(s.Age);
5 tw.WriteLine(s.GPA);
6 tw.Flush(); // Ensure the TextWriter buffer is empty
7 }
8 void ReadFromStream(Stream stm, Student s) {
9 TextReader tr = new StreamReader(stm);
10 s.Name = tr.ReadLine();
11 s.Age = Int32.Parse(tr.ReadLine());
12 s.GPA = Double.Parse(tr.ReadLine());
13 }
Programowanie Obiektowe 226
Ć" Aańcuchy znaków jako strumienie:
1 using System;
2 using System.IO;
3 using System.Text;
4 class Test {
5 static void Main() {
6 StringBuilder sb = new StringBuilder();
7 StringWriter sw = new StringWriter(sb);
8 WriteHello(sw);
9 Console.WriteLine(sb);
10 }
11 static void WriteHello(TextWriter tw) {
12 tw.Write("Hello, String I/O!");
13 }
14 }
Programowanie Obiektowe 227
Ć" Asynchroniczne wejście/wyjście:
1 usingSystem;
2 usingSystem.IO;
3 usingSystem.Text;
4 classAsyncReadFun{
5 classAsyncReadState{
6 publicStreamstm;// Underlying stream
7 publicbyte[]buf=newbyte[256];// Read buffer
8 publicStringBuildersb=newStringBuilder();// Result buffer
9 publicAsyncCallbackacb=newAsyncCallback(ReadCallback);
10 }
11 staticvoidAReadCallback(IAsyncResultiar) {
12 AsyncReadStatears= (AsyncReadState)iar.AsyncState;
13 intbytes=ars.stm.EndRead(iar);// Get count of bytes read
14 if(bytes> 0) {// Copy read bytes and restart read
15 ars.sb.Append(Encoding.ASCII.GetString(ars.buf, 0,bytes));
16 Console.WriteLine("Read chunk of {0} bytes",bytes);
17 ars.stm.BeginRead(ars.buf, 0,ars.buf.Length,ars.acb,ars);
18 }
Programowanie Obiektowe 228
19 }
20 staticvoidMain(string[]args) {
21 // Open the stream & start reading
22 Streams=File.OpenRead(args[0]);
23 AsyncReadStatears=newAsyncReadState();
24 ars.stm=s;// Save the stream reference
25 IAsyncResultiar=s.BeginRead(ars.buf, 0,ars.buf.Length,
26 ars.acb,ars);
27 // Download a file while we re reading the stream
28 System.Net.WebClientwc=newSystem.Net.WebClient();
29 wc.DownloadFile("http://www.oreilly.com","index.html");
30 Console.WriteLine("Finished downloading index.html.");
31 // Wait until the async read is done
32 iar.AsyncWaitHandle.WaitOne();
33 Console.WriteLine(ars.sb);
34 }
35 }
Programowanie Obiektowe 229
Typy ogólne  generics
Ć" Idea mniej-więcej ta sama co szablonów w C++: typy sparametryzowane
typami.
Ć" Różnice:
î% Parametrami mogÄ… być tylko typy.
î% ZaÅ‚ożenia co do typu parametryzujÄ…cego muszÄ… być ujawnione w
deklaracji klasy ogólnej.
î% Typy kompilowane do kodu poÅ›redniego, typy szczegółowe powstajÄ…
dopiero w wyniku działania komplatora JIT
Ć" Przykład korzystania:
1 Stack stack = new Stack();
2 for (int i=0; i<10; i++)
3 stack.Push(i);
4 for (int i=0; i<10; i++)
5 Console.WriteLine(stack.Pop());
Programowanie Obiektowe 230
Ć" Kolekcje
î% ICollection
f& Count,
f& CopyTo().
î% IEnumerable
f& GetEnumerator().
î% IEnumerator
f& Current,
f& MoveNext(), Reset().
î% foreach uÅ‚atwia używanie enumeratorów.
î% wersja 2.0  iteratory, yield return oraz yield break
1 public IEnumerator GetEnumerator() {
2 for (int i = count - 1; i >= 0; --i) {
3 yield return items[i];
4 }
5 }
î% PrzestrzeÅ„ nazw System.Collections.Generic.
Programowanie Obiektowe 231
Ć" Ogólne klasy
î% Comparer  klasa bazowa dla imlplementacji IComparer.
î% Dictionary  sÅ‚ownik (kolekcja par klucz wartość).
î% Dictionary.KeyCollection  Kolekcja kluczy sÅ‚ownika.
î% Dictionary.ValueCollection  Kolekcja wartoÅ›ci sÅ‚ownika.
î% EqualityComparer  klasa bazowa dla implementacji
IEqualityComparer.
î% KeyNotFoundException  wyjÄ…tek dla sÅ‚owników.
î% LinkedList  lista dwukierunkowa.
î% LinkedListNode  wÄ™zeÅ‚ listy dwukierunkowej.
î% List  lista indeksowana.
î% Queue  kolejka.
î% SortedDictionary  sÅ‚ownik posortowany.
î% SortedDictionary.KeyCollection.
î% SortedDictionary.ValueCollection.
î% SortedList  kolekcja par klucz-wartość posortowanych przy użyciu
implementacji IComparer.
î% Stack  stos.
Programowanie Obiektowe 232
Ć" Ogólne interfejsy
î% ICollection : IEnumerable, IEnumerable
f& Count, IsReadOnly,
f& Add(), Clear(), Contains(), CopyTo(), Remove().
î% IComparer
f& Compare()
î% IDictionary :
ICollection>,
IEnumerable>, IEnumerable
f& Item[], Keys, Values,
f& Add(), ContainsKey(), Remove(), TryGetValue()
î% IEnumerable : IEnumerable
f& GetEnumerator()
î% IEnumerator : IDisposable, IEnumerator
f& Current,
f& MoveNext(), Reset()
Programowanie Obiektowe 233
î% IEqualityComparer
f& Equals(), GetHashCode()
î% IList : ICollection, IEnumerable, IEnumerable
f& Item[],
f& IndexOf(), Insert(), RemoveAt()
Programowanie Obiektowe 234
Ć" Ogólne struktury
î% Dictionary.Enumerator
î% Dictionary.KeyCollection.Enumerator
î% Dictionary.ValueCollection.Enumerator
î% KeyValuePair
î% LinkedList.Enumerator
î% List.Enumerator
î% Queue.Enumerator
î% SortedDictionary.Enumerator
î% SortedDictionary.KeyCollection.Enumerator
î% SortedDictionary.ValueCollection.Enumerator
î% Stack.Enumerator
Programowanie Obiektowe 235
Ć" Przykład użycia słownika:
1 Dictionary wzrost =
2 new Dictionary();
3 wzrost.Add("Mariusz", 197);
4 wzrost.Add("Marcin", 211);
5 Console.WriteLine("Mariusz ma {0} cm wzrostu, a Marcin {1}",
6 wzrost["Mariusz"], wzrost["Marcin"]);
Programowanie Obiektowe 236
Ć" Definiowanie klas ogólnych:
1 public class Tablica
2 {
3 T[] tablica;
4 Tablica(int n) {
5 tablica = new T[n];
6 }
7 T this[int i] { return tablica[i]; }
8 ...
9 }
Programowanie Obiektowe 237
Ć" Założenia co do typów-parametrów:
1 public class Dictionary
2 where K: IComparable
3 {
4 public void Add(K key, V value)
5 {
6 ...
7 if (key.CompareTo(x) < 0) {...}
8 ...
9 }
10 }
Programowanie Obiektowe 238
Ć" Metody ogólne
1 public static swap(ref T x, ref T y)
2 {
3 T z = x;
4 x = y;
5 y = z;
6 }
Ć" Założenia co do typów-parametrów metod:
1 public static Min(params T[] tab)
2 where T : IComparable
3 {
4 T min = tab[0];
5 for (int i=0; i6 if (tab[i] < min)
7 min = tab[i];
8 return min;
9 }
Programowanie Obiektowe 239
WyjÄ…tki
Ć" Schemat:
1 try {
2 ...
3 }
4 catch (ExceptionA e) {
5 ...
6 }
7 catch (ExceptionB e) {
8 ...
9 }
10 finally {
11 ...
12 }
Ć" Musi wystąpić przynajmniej jedna sekcja catch lub finally.
Ć" catch i finally się wzajemnie nie wykluczają jak w C++.
Programowanie Obiektowe 240
Ć" Tylko pierwsza pasująca sekcja catch jest wykonywana.
Ć" Klasy wyjątków muszą dziedziczyć po System.Exception.
Ć" Klasa System.Exception zawiera m.in. własności:
î% Message  opis wyjÄ…tku,
î% StackTrace  stos wywoÅ‚aÅ„,
î% TargetSite  metoda, która zgÅ‚osiÅ‚a wyjÄ…tek,
î% Data  sÅ‚ownik z dodatkowymi informacjami o wyjÄ…tku.
Ć" Przykład:
1 publicclassWeightCalculator
2 {
3 publicstaticfloatCalcBMI(floatkilos,floatmeters) {
4 if(meters< 0 ||meters> 3)
5 thrownewArgumentException("Impossible Height","meters");
6 if(kilos< 0 ||kilos> 1000)
7 thrownewArgumentException("Impossible Weight","kilos");
8 returnkilos/ (meters"meters);
9 }
10 }
Programowanie Obiektowe 241
11 classTest{
12 staticvoidMain() {
13 TestIt();
14 }
15 staticvoidTestIt() {
16 try{
17 floatbmi=WeightCalculator.CalcBMI(100, 5);
18 Console.WriteLine(bmi);
19 }
20 catch(ArgumentExceptionex) {
21 Console.WriteLine(ex);
22 }
23 finally{
24 Console.WriteLine("Thanks for running the program");
25 }
26 Console.Read();
27 }
28 }
Programowanie Obiektowe 242
Tryb niechroniony - unsafe
Ć" Metody i bloki niechronione oznacza się słowem kluczowym unsafe.
Ć" Używanie wskazników możliwe jest tylko w trybie niechronionym.
Konieczne jest wówczas  przyszpilowanie obiektu deklaracją fixed.
Ć" Przykład:
1 unsafe void RedFilter(int[,] bitmap) {
2 const int length = bitmap.Length;
3 fixed (int* b = bitmap) {
4 int* p = b;
5 for(int i = 0; i < length; i++)
6
*p++ &= 0xFF;
7 }
8 }
Programowanie Obiektowe 243
Ć" Przykład mnożenia macierzy:
1 public static Macierz operator*(Macierz m1, Macierz m2) {
2 Macierz m3 = new Macierz(m1.LWierszy, m2.LKolumn);
3 unsafe {
4 fixed (double* pocz1 = m1.wartości) {
5 fixed (double* pocz2 = m2.wartości) {
6 fixed (double* pocz3 = m3.wartości) {
7 double
*p1 = pocz1,
8 koniec1 = pocz1+m1.LWierszy*m1.LKolumn;
9 while (p1 < koniec1)
10 {
11 ...
12 }
13 }
14 }
15 }
16 }
17 }


Wyszukiwarka


Podobne podstrony:
Programowanie w C i pro obiektowe wyklad C
Programowanie i jezyk C Wyklad 02 Instrukcje
Programowanie Obiektowe Ćwiczenia 5
[C ]Rataj Podstawy programowania obiektowego
Programowanie Obiektowe W Visual Basic Net Dla Ka dego
JavaScript Programowanie obiektowe
Programowanie obiektowe pojęcia
Podstawy Programowania 04 Programowanie Obiektowe
Jezyk C?ektywne programowanie obiektowe cpefpo
Programowanie Obiektowe W Pythonie
świerszczyński,programowanie obiektowe,Konstruktory i destruktory
Programowanie i jezyk C Wyklad 01 Typy danych
Programowanie obiektowe i C

więcej podobnych podstron