Author
vutuyen
View
216
Download
0
Embed Size (px)
Programowanie obiektowe C++Programowanie zorientowane obiektowo
Wykad 1
Witold [email protected]
10/10/2011
mailto:[email protected]
Prawa autorskie itp.
Wiele slajdw do tego wykadu powstao w oparciu o: slajdy Bjarne Stroustrupa
do kursu Foundations of Engineering II (C++) prowadzonego w Texas A&M Universityhttp://www.stroustrup.com/Programming
przykadowe programy Jerzego Grbosza do ksiki Symfonia C++ Standardhttp://www.ifj.edu.pl/~grebosz/symfonia_c++_std_p.html
Dzikuj dr in. lek. med. Marcinowi Masalskiemu za udostpnienie materiaw do wykadu w roku ak. 2010/11
http://www.stroustrup.com/Programminghttp://www.ifj.edu.pl/~grebosz/symfonia_c++_std_p.html
Program wykadw0. Bezpieczestwo typw. Kontener vector. Obsuga bdw (26/09/2011)
1. Abstrakcja i enkapsulacja: klasy i struktury. Typ wyliczeniowy (10/10/2011)
2. Polimorfizm: przeadowanie funkcji i operatorw (24/10/2011)
3. Zarzdzanie pamici: konstruktory, destruktory. Konwersje (21/11/2011)
4. Dziedziczenie (05/11/2011)
5. Programowanie uoglnione: szablony (19/12/2011)
6. Projektowanie programw orientowanych obiektowo (02/01/2012)
7. Kolokwium zaliczeniowe (16/01/2012)
Program laboratorium Techniki programowania orientowanego obiektowo
w jzyku C++ Enkapsulacja i polimorfizm (lista 1) Zarzdzanie pamici (lista 2) Dziedziczenie i abstrakcja (lista 3) Programowanie uoglnione (lista 4?)
Obsuga bdw i odrobaczanie programu Korzystanie z biblioteki standardowej
Materiay
Literatura Bjarne Stroustrup. Programowanie: Teoria i praktyka z
wykorzystaniem C++. Helion (2010) Jerzy Grbosz. Symfonia C++ standard. Edition 2000 (2008) Dowolny podrcznik programowania zorientowanego obiektowo
w jzyku C++ w standardzie ISO 98
rodowisko programistyczne Microsoft Visual C++ (rekomendowane) Dowolne rodowisko korzystajce z GCC
Warunki zaliczenia Kolokwium zaliczeniowe
16/01/2012 w czasie wykadu jedno kolokwium poprawkowe
zaliczenie od >50%
Uwaga! jeli kto ma braki z programowania zapraszam na wykad pt. Jzyki programowania
w rod o 18.55 do sali 1.30/C-13
Zasady Nie toleruj plagiatw
dot. programw na laboratorium
Nie toleruj cigania dot. kolokwium i sprawdzianw na laboratorium
Zachcam do korzystania z konsultacji ze mn: PT 10-11, pok. 118A/D-1 pomidzy sob
Plan na dzi Klasy
Implementacja i interfejs Konstruktory Funkcje skadowe Skadowe stae Skadowe statyczne
Typ wyliczeniowy
Klasy Klasa bezporednio reprezentuje pojcie w programie
Jeli o czym mona myle jako o oddzielnym bycie, to prawdopodobnie moe to by klas lub obiektem klasy
Np. wektor, macierz, strumie wejciowy, acuch znakowy, szybka transformata Fouriera, kontroler zaworu, rami robota, sterownik urzdzenia, obraz na ekranie, okno dialogowe, wykres, okno, odczyt temperatur, zegar
Klasa jest typem zdefiniowanym przez uytkownika, ktry okrela jak tworzy i uywa obiekty tego typu
Klasy po raz pierwszy wprowadzono w jzyku Simula67
Klasa, obiekt, zmiennaclass Pralka { // ta klasa nazywa si Pralka
// Ciao klasy// ...
};
Pralka czerwona; // definicja zmiennej czerwona typu Pralka// powstaje nowy obiekt, ktry otrzymuje nazw czerwona
int numer; // definicja zmiennej numer typu int// powstaje nowy obiekt, ktry otrzymuje nazw numer
Pralka *wskaznik; // definicja wskaznika na typ Pralka
Pralka &ruda = czerwona; // definicja referencji ruda do zmiennej czerwona
Sowniczek:
Klasa typ danych uytkownika
Obiekt miejsce w pamici przechowujce dane okrelonego typu
Zmienna nazwany obiekt
Dane skadowe klasyclass Pralka { // ta klasa nazywa si Pralkapublic:
//
int nr_programu; // dane skadowe (przechowuj informacje)float temperatura_prania;string model;
//
};
czerwona.model = Frania; // dostp do danej skadowej model zmiennej czerwona
wskaznik = &czerwona; // ustawienie wskaznika na zmiennej czerwona
wskaznik->model = Frania; // dostp przez wskanik
ruda.model = Frania; // dostp przez referencj
Funkcje skadowe klasy (metody)class Pralka { // ta klasa nazywa si Pralkapublic:
int pierz(int program); // funkcje skadowe (robi co z danymi skadowymi)void wiruj(int minuty);
int nr_programu; // dane skadowe (przechowuj informacje)float temperatura_prania;string model;
float krochmalenie(void); // znowu funkcja skadowa};
int x = czerwona.pierz(1); // wywoanie funkcji skadowej pierz() dla czerwona
int y = ruda.pierz(2); // wywoanie funkcji skadowej pierz() dla referencji ruda
wskaznik = &czerwona;
int z = wskaznik->pierz(3); // wywoanie funkcji skadowej pierz() dla wskaznika
Definiowanie funkcji skadowychwewntrz ciaa funkcji inline
class osoba {
public:
string nazwisko; int wiek;
// Definicje funkcji skadowych: ====================================void zapamietaj(const string &napis, int lata) {
nazwisko = napis;wiek = lata;
} // -------------------------------------------------------------------------------------------------------------
void wypisz() {cout
Definiowanie funkcji skadowych na zewntrz ciaa funkcji
class osoba {
public:
string nazwisko; int wiek;
// Deklaracje funkcji skadowych: ================================void zapamietaj(const string &napis, int lata);void wypisz();
};
// Definicje funkcji skadowych: ====================================void osoba::zapamietaj(const string &napis, int lata) {
nazwisko = napis;wiek = lata;
} // -------------------------------------------------------------------------------------------------------------void osoba::wypisz() {
cout
Inicjowanie obiektu typu uytkownika konstruktor
Tworzc wasny typ danych potrzebujemy okreli sposb inicjowania obiektw tego typu: suy do tego konstruktor
Konstruktor zawsze nazywa si tak samo jak jego klasaclass osoba {
public:
string nazwisko; int wiek;
// Deklaracje konstruktorw: =================================== osoba(const string &napis, int lata) : nazwisko(napis), wiek(lata) { }; osoba(int lata) : nazwisko("NN"), wiek(lata) { };
// Deklaracje funkcji skadowych: ================================void zapamietaj(const string &napis, int lata);void wypisz();
};
class X { // klasa o nazwie Xpublic: // publiczne skadowe klasy interfejs uytkownika
// (dostpne dla wszystkich)// funkcje// typy// dane (najczciej lepiej, eby byy prywatne)
private: // priwatne skadowe klasy szczegy implementacyjne// (dostpne tylko dla skadowych klasy)
// funkcje// typy// dane
};
Interfejs i implementacja klasy
Klasy i strukturyKlasy mog mie dwie bliniacze formy: class i struct
Skadowe klasy s domylnie prywatne, czyli zapis:
class X { int mf();
// };
oznacza tyle co:
class X {private:
int mf();//
}; Wic:
X x; // zmienna x typu Xint y = x.mf(); // bd kompilacji: mf jest prywatna (niedostpna)
Klasy i struktury (2)Klasy mog mie dwie bliniacze formy: class i struct
Skadowe struktury s domylnie publiczne, czyli zapis:
struct X { int m;
// };
oznacza tyle co:
class X {public:
int m;//
};
Rodzi si pytanie po co ukrywa skadowe?
Po co komu prywatne skadowe? Aby stworzy przejrzysty interfejs klasy
Dane i zagmatwane funkcje mona ukry Aby kontrolowa niezmienniki
Dziki ograniczonemu zbiorowi funkcji z dostpem Aby uatwi debugowanie
Zawenie grona podejrzanych Aby umoliwi zmian reprezentacji (danych skadowych)
Wystarczy zmieni ograniczony zbir funkcji W przypadku skadowej publicznej nie mona nigdy
wiedzie, kto j uywa
// najprostsza wersja Date (tylko dane) struct Date {
int y,m,d; // rok, miesic, dzie};
Date my_birthday; // zmienna typu Date (obiekt)
my_birthday.y = 12;my_birthday.m = 30;my_birthday.d = 1950; // Ups! (nie ma dnia 1950 w miesicu 30)
// Bd nie zosta zgoszony, ale dalej w programie// bdziemy mieli problemy
Date:my_birthday: y
m
d
Struktura tylko dane(jak w jzyku C)
// prosta wersja Date (dodalimy kilka funkcji pomocnicznych)struct Date {
int y,m,d; // rok, miesic, dzie};
Date my_birthday; // zmienna typu Date (obiekt)
// funkcje pomocnicze:
void init_day(Date& dd, int y, int m, int d); // sprawd poprawno daty i inicjalizujvoid add_day(Date&, int n); // zwiksz obiekt Date o n dni//
init_day(my_birthday, 12, 30, 1950); // bd czasu wykonania: // nie ma dnia 1950 w miesicu 30
wietnie, ale nie ma gwarancji, e uytkownik struktury uyje funkcji init_day() po utworzeniu zmiennej typu Date.
Date:my_birthday: y
m
d
Struktura tylko dane(jak w jzyku C) podejcie 2
// prosta Date // gwarantuje inicjalizacj przy uyciu konstruktora// zapewnia pewn wygod notacyjnstruct Date {
int y,m,d; // rok, miesic, dzieDate(int y, int m, int d); // konstruktor: sprawdza poprawno daty i inicjujevoid add_day(int n); // zwiksza dat o n dni
};
// Date my_birthday; // bd: my_birthday nie zainicjowane (I dobrze!)Date my_birthday(12, 30, 1950); // ups! Bd czasu wykonaniaDate my_day(1950, 12, 30); // okmy_day.add_day(2); // 1 stycznia 1951my_day.m = 14; // grrrhh! (teraz my_day jest niepoprawn dat)
wietnie, poprawna inicjacja jest zagwarantowana. Niestety, publiczny dostp do danych skadowych Date grozi zepsuciem daty
1950
30
12
Date:my_birthday: y
m
d
Struktura w stylu C++
// prosta Date (z kontrol dostpu)class Date {
int y,m,d; // rok, miesic, dziepublic:
Date(int y, int m, int d); // konstruktor: sprawdza poprawno daty i inicjuje
// funkcje dostpowe:void add_day(int n); // zwiksza dat o n dniint month() { return m; } int day() { return d; }int year() { return y; }
};
// Date my_birthday(1950, 12, 30); // okcout
Niezmienniki Pojcie poprawnej daty jest szczeglnym przypadkiem pojcia
poprawnej wartoci Zasada: zagwarantowa poprawne wartoci dla
projektowanego typu (poprawny stan obiektu) Inaczej musielibymy cay czas sprawdza poprawno danych
lub liczy, e zrobi to uytkownik klasy Regu opisujc poprawn warto nazywa si
niezmiennikiem W przypadku daty jest to wyjtkowo trudne (28 luty, rok przestpny itd.)
Jeli nie mona znale dobrego niezmiennika pracujesz na samych czystych danych Uyj struktury Pierwsz opcj jest jednak zawsze szukanie niezmiennikw!
// prosta Date (niektrzy wol interfejs klasy na pocztku dlaczego?)class Date {public:
Date(int y, int m, int d); // konstruktor: sprawdza poprawno daty i inicjujevoid add_day(int n); // zwiksza dat o n dniint month();//
private:int y,m,d; // rok, miesic, dzie
};
Date::Date(int yy, int mm, int dd) // definicja konstruktora klasy:y(yy), m(mm), d(dd) { /* */ }; // inicjacja skadowych
void Date::add_day(int n) { /* */ }; // definicja funkcji
1950
30
12
Date:my_birthday: y
m
d
Prosty konstruktor klasy
// prosta Date (co zrobimy z nieprawidow dat)class Date {public:
class Invalid { }; // uyta jako rakieta sygnalizacyjna// przy obsudze wyjtkw
Date(int y, int m, int d); // sprawdza poprawno daty i inicjuje//
private:int y,m,d; // rok, miesic, dziebool check(int y, int m, int d); // czy (y,m,d) jest poprawn dat?
};
Date:: Date(int yy, int mm, int dd): y(yy), m(mm), d(dd) // inicjuje dane skadowe
{if (!check(y,m,d)) throw Invalid(); // sprawdza poprawno daty
}
Konstruktor z kontrol poprawnoci
Wyliczenia Wyliczenie enum (ang. enumaration) jest typem uytkownika
okrelajcym zestaw wartoci (elementy wyliczenia)
Na przykad:enum Month {
jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec};
Month m = feb;m = 7; // bd: nie mona przypisa int do Monthint n = m; // ok: moemy dosta warto liczbow MonthMonth mm = Month(7); // konwersja typu int na Month (nie sprawdzana)
Zastosowanie wylicze Prosta lista staych
enum { red, green }; // enum { } nie definiuje zakresuint a = red; // red jest dostpne tutajenum { red, blue, purple }; // bd: red jest ju zdefiniowany
Typ z list staychenum Day { sun, mon, tue, /* */ }; // domylnie: sun==0, mon==1, tue==2enum Color { red=100, green=1, blue=10, /* */ }; Day m1 = sun;Day m2 = red; // bd: red nie jest wartoci DayDay m3 = 7; // bd: 7 nie jest wartoci Dayint i = m1; // ok: element wyliczenia jest konwertowany do
// swojej wartoci, i==0
// prosta Date (uywa typu Month)class Date {public:
enum Month {jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
};Date(int y, Month m, int d); // sprawdza poprawno daty i inicjuje//
private:int y; // rokMonth m;int d; // dzie
};
Date my_birthday(1950, 30, Date::dec); // bd: 2. argument nie jest miesicemDate my_birthday(1950, Date::dec, 30); // ok enum pomaga kontrolowa poprawno
// zwr te uwag na zakres: Date::dec
1950
30
12
Date:my_birthday: y
m
d
Klasa z wyliczeniem
class Date {public:
// int day() const { return d; } // stay skadnik: nie moe modyfikowavoid add_day(int n); // nie-stay skadnik: moe modyfikowa//
};
Date d(2000, Date::jan, 20); // zmienna d typu Dateconst Date cd(2001, Date::feb, 21); // staa cd typu Date
cout
//Date d(2004, Date::jan, 7); // zmiennaconst Date d2(2004, Date::feb, 28); // staad2 = d; // bd: d2 jest constd2.add(1); // bd: d2 jest constd = d2; // w porzdkud.add(1); // w porzdku
d2.f(); // Taka operacja powinna zosta wykonana wtedy i tylko wtedy, gdy// funkcja skadowa f() nie modyfikuje danych skadowych obiektu d2// Jak to zapewni? (zakadajc, e tego wanie chcemy)
Skadniki stae klasy (2)
// Rozrnij pomidzy funkcjami, ktre mog modyfikowa obiekty// I tymi, ktre nie mog zwanymi staymi funkcjami skadowymiclass Date {public:
// int day() const; // pobierz dzie (w zasadzie jego kopi)// void add_day(int n); // przesu dat o n do przodu//
};
const Date dx(2008, Month::nov, 4);int d = dx.day(); // w porzdkudx.add_day(4); // bd: nie mona modyfikowa staych danych
Skadniki stae klasy (3)
Dobry interfejs klasy Minimalny
Tak may jak to moliwe Kompletny
I nie mniejszy Bezpieczny dla typw (ang. type-safe)
Uwaga na kolejno argumentw Poprawnie okrela stae skadniki klasy
(ang. const-correct)
Minimalny zestaw skadowych Najbardziej podstawowe operacje
Konstruktor domylny (domylnie: nie robi nic lub brak domylnego konstruktora jeli zadeklarowano inny konstruktor
Konstruktor kopiujcy (domylnie: kopiuje skadowe) Operator przypisania (domylnie: kopiuje skadowe) Destruktor (domylnie: nie robi nic)
Na przykadDate d; // bd: brak domylnego konstruktora (zadeklarowalimy inny!)
Date d2 = d; // ok: inicjacja kopi (kopiuje elementy domylne)
d = d2; // ok: przypisanie kopii (kopiuje elementy domylne)
Interfejs klasy i funkcje pomocnicze Chcemy minimalny interfejs klasy (zbir funkcji
pomocnicznych), bo to: Uatwia zrozumienie klasy Upraszcza debugowanie Upraszcza pielgnacj
Potrzebujemy funkcji pomocniczych, operujcych na obiektach klasy, ale zdefiniowanych poza klas, np. == (rwno) , != (nierwno) next_weekday(), next_Sunday()
Date next_Sunday(const Date& d){
// ma dostp do obiektu d poprzez d.day(), d.month(), oraz d.year()// tworzy nowy obiekt typu Date ktry zwraca
}
Date next_weekday(const Date& d) { /* */ }
bool operator==(const Date& a, const Date& b){
return a.year()==b.year()&& a.month()==b.month()&& a.day()==b.day();
}
bool operator!=(const Date& a, const Date& b) { return !(a==b); }
Funkcje pomocnicze
Funkcje zaprzyjanione Czasem warto da funkcji pomocniczej dostp do prywatnych skadowych klasy
np. zamiast tworzenia funkcji day(), month(), year().
class Date {
public:// ..friend void print(Date &d) const; // funkcja zaprzyjaniona wywietlajca dat
private:int y,m,d;
};
void print(Date &d) const {cout
Skadniki statyczne...czyli skadniki wsplne dla wszystkich obiektw danej klasy (zmienne globalna dla klasy) Zastosowania:
Do porozumiewania si pomidzy obiektami klasy (jako flaga) Jako istniejcych licznik obiektw danej klasy Gdy pewna cecha bdzie si zmienia jednoczenie dla
wszystkich obiektw danej klasy Dostp do wejcia/wyjcia (np. pliku) - wsplnego dla
wszystkim obiektw klasy
Skadniki statyczne przykad
class piorko {
enum tak_czy_nie { nie, tak } ;
int poz_x, poz_y ;static int zezwolenie ;string kolor ;
public :// funkcje ------------------------------------------------------------ void jazda(int x , int y); static void czy_mozna(tak_czy_nie odp){ zezwolenie = odp ; // skadnik statyczny zezwolenie // poz_x = 5 ; // bd ! bo skadnik zwyky poz_x
// Funkcja statyczna moe odwoywa si// tylko do skadnikw statycznych klasy
}piorko(const string kol) : kolor(kol), poz_x(0), poz_y(0) { };
};
dana statyczna
tu: prywatna
funkcja statyczn
a
Skadniki statyczne przykad (kont.)void piorko::jazda(int x , int y) {
cout
Dzi najwaniejsze byo to, e...
Klasa reprezentuje pojcie Obiekt jest ucielenieniem tej klasy
Zmienna jest nazwanym obiektem
Oddzielamy interfejs od implementacji (enkapsulacja)
Zasady tworzenia dobrego interfejsu: minimalny, ale kompletny, zawiera funkcje zaprzyjanione bezpieczny dla typw, okrela skadowe stae
A za 2 tygodnie...
Polimorfizm:przeadowanie funkcji i operatorw