Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Zasady zaliczenia Warunki uzyskania zaliczenia:

Podobne prezentacje


Prezentacja na temat: "Zasady zaliczenia Warunki uzyskania zaliczenia:"— Zapis prezentacji:

1 Zasady zaliczenia Warunki uzyskania zaliczenia:
Samodzielne wykonanie i prezentacja zadanego programu zaliczeniowego. Umiejętność wyjaśnienia instrukcji pojawiających się w kodzie oraz wprowadzenia drobnych modyfikacji. Kolokwium ( ) 3) Alternatywną możliwością zaliczenia jest aktywność na zajęcia (3 oceny bdb za pojawiające się na zajęciach zadania)

2 Programowanie obiektowe
Metodologia tworzenia programów komputerowych, która definiuje programy za pomocą "obiektów" - elementów łączących stan (czyli dane) i zachowanie (czyli procedury, tu: metody). Obiektowy program komputerowy wyrażony jest jako zbiór takich obiektów, komunikujących się pomiędzy sobą w celu wykonywania zadań. Podejście to różni się od tradycyjnego programowania proceduralnego, gdzie dane i procedury nie są ze sobą bezpośrednio związane. Programowanie obiektowe ma ułatwić pisanie, konserwację i wielokrotne użycie programów lub ich fragmentów

3 Cechy podejścia obiektowego
Wszystko jest obiektem. Program jest zbiorem obiektów, które poprzez wysyłanie komunikatów mówią sobie nawzajem, co robić. Każdy obiekt posiada swą własną pamięć, na którą składają się inne obiekty. Każdy obiekt posiada swój własny typ. Wszystkie obiekty danego typu mogą otrzymywać te same komunikaty. Obiekt ma stan, zachowanie i tożsamość.

4 Abstrakcja Każdy obiekt w systemie służy jako model abstrakcyjnego "wykonawcy", który może wykonywać pracę, opisywać i zmieniać swój stan, oraz komunikować się z innymi obiektami w systemie, bez ujawniania, w jaki sposób zaimplementowano dane cechy.

5 Enkapsulacja Czyli ukrywanie implementacji, hermetyzacja. Zapewnia, że obiekt nie może zmieniać stanu wewnętrznego innych obiektów w nieoczekiwany sposób. Tylko wewnętrzne metody obiektu są uprawnione do zmiany jego stanu. Każdy typ obiektu prezentuje innym obiektom swój "interfejs", który określa dopuszczalne metody współpracy.

6 Polimorfizm Referencje i kolekcje obiektów mogą dotyczyć obiektów różnego typu, a wywołanie metody dla referencji spowoduje zachowanie odpowiednie dla pełnego typu obiektu wywoływanego. Jeśli dzieje się to w czasie działania programu, to nazywa się to późnym wiązaniem lub wiązaniem dynamicznym. Niektóre języki udostępniają bardziej statyczne (w trakcie kompilacji) rozwiązania polimorfizmu - na przykład szablony i przeciążanie operatorów w C++.

7 Dziedziczenie Porządkuje i wspomaga polimorfizm i enkapsulację dzięki umożliwieniu definiowania i tworzenia specjalizowanych klas na podstawie bardziej ogólnych. Dla klas specjalizowanych nie trzeba redefiniować całej funkcjonalności, lecz tylko tę, której nie ma obiekt ogólniejszy.

8 Klasy class nazwa_klasy { //Składniki i funkcje składowe };
Przykład 1. class osoba { char nazwisko[80]; int wiek; Przykład 2. class samochod { char marka[60]; int rok_produkcji;

9 Tworzenie obiektów danej klasy
Deklaracja obiektu danej klasy: nazwa_klasy nazwa_obiektu; Odwołanie do składników i funkcji składowych danej klasy: nazwa_obiektu.skladnik nazwa_obiektu.funkcja(argumenty) Przykład: class osoba{ int wiek; }; Main(){ Osoba Kowalski; Kowalski.wiek=55; ... }

10 Klasy Ćwiczenie 1. Napisz klasę plytaCD, zawierającą składniki reprezentujące dane o autorze, tytule, wydawcy, roku wydania, liczbie utworów, czasie trwania. Utwórz obiekt tej klasy i ustal wartość składnika rok wydania. Ćwiczenie 2. Napisz klasę Zwierze, zawierającą składniki reprezentujące dane o rodzaju, rodzinie, rzędzie, gromadzie, typie, królestwie, liczbie kończyn, objętości mózgu, masie.

11 Ukrywanie informacji Rodzaje dostępu do składnika klasy:
public – składnik dostępny bez ograniczeń, private – dostępny tylko dla funkcji składowych danej klasy, protected – dostępny tak jak składniki private, ale dodatkowo dostępny też dla klas wywodzących się z danej klasy. Jeśli w definicji klasy nie określamy sposobu dostępu, to rodzaj dostępu domyślnie jest ustalany jako private.

12 Funkcje składowe(1) Definiowanie funkcji: 1) W definicji klasy, np.:
class osoba{ char nazwisko[100]; public: void przedstaw(){ cout<<nazwisko<<endl; } }; Zalecane dla krótkich funkcji.

13 Funkcje składowe(2) 2) W definicji klasy, np.: class osoba{
char nazwisko[100]; public: //tylko deklaracja void pobierz_dane(); }; //definicja funkcji poza definicją klasy void osoba::pobierz_dane() { //instrukcje } Zalecane dla dłuższych funkcji.

14 Funkcje składowe(3) Ćwiczenie 3.
Napisz funkcje składowe klasy plytaCD: -wprowadzającą dane do składników obiektów, Do odczytu wartości zmiennej z klawiatury można użyć instrukcji: cin >> nazwa_zmiennej; -wyświetlajacą dane obiektu, -zwracającą średni czas trwania utworu.

15 Konstuktory (1) Konstruktor to specjalna funkcja, która jest uruchamiana automatycznie przy definiowaniu każdego obiektu danej klasy. Deklaracja konstruktora nazwa_klasy (argumenty); Zasady deklaracji: nazwa konstruktora identyczna z nazwą klasy, nie określa się zwracanego typu (nawet void), nie są dziedziczone. Klasa może mieć wiele konstruktorów (konstruktory mogą być przeładowane). Wykonywany jest wtedy konstruktor z odpowiednią liczbą i rodzajem argumentów.

16 Konstuktory (2) Przykład: class plyta { char tytul[100]; int cena;
plyta (char tyt[200], int c); }; plyta::plyta(char tyt[200], int c){ strcpy(tytul, tyt); cena=c; } Ćwiczenie 4. Napisz dowolny konstruktor klasy Zwierze.

17 Konstuktory (3) Konstruktor domniemany – konstruktor, który można wywołać bez argumentów. Klasa może mieć tylko jeden konstruktor domniemany. Jeśli klasa nie ma żadnego konstruktora, to kompilator automatycznie generuje konstruktor domniemany. Konstruktorami domniemanymi są także konstruktory posiadające wyłącznie argumenty domniemane, np.: class abc{ //... public: abc(int); abc(float); //deklaracja konstruktora domniemanego abc(char *b = NULL, float a = 6.3, int c = 2); };

18 Konstuktory (4) Konstruktor kopiujący – konstruktor, który można wywołać z argumentem będącym referencją obiektu danej klasy. klasa::klasa( klasa &) Konstruktor kopiujący jest wykorzystywany do tworzenia obiektu będącego kopią obiektu wskazanego argumentem. Jeśli klasa nie ma zdefiniowanego konstruktora kopiującego, to kompilator tworzy go automatycznie. Ćwiczenie 5 Napisz konstruktor kopiujący klasy Zwierze, który uaktualnia globalną zmienną reprezentującą liczbę aktualnie istniejących obiektów tej klasy.

19 Destruktory(1) Destruktorem klasy K jest jej funkcja składowa o nazwie ~K. Funkcja ta jest wywoływana automatycznie zawsze, gdy obiekt jest likwidowany. Destruktor nie jest obowiązkowym składnikiem klasy. Przykłady zastosowania destruktorów: -odświeżenie ekranu po usunięciu obiektu (np. okienka), -zwalnianie obszaru pamięci zarezerwowanego dla obiektu, -liczenie obiektów danej klasy, -zapis informacji o usuwanych obiektach. Deklaracja destruktora: ~nazwa_klasy(); Zasady deklaracji: -brak zwracanego typu, -brak argumentów, -nazwa destruktora to nazwa klasy poprzedzona znakiem ~.

20 Destruktory(2) Jawne wywołanie destruktora: obiekt.~klasa();
wskaznik->klasa(); This->~klasa(); //z wnętrza klasy Ćwiczenie 6. Napisz destruktor klasy Płyta, który wypisze na ekran wybrane informacje o płycie.

21 Funkcje zaprzyjaźnione(1)
Funkcja zaprzyjaźniona z klasą to funkcja, która (mimo, że nie jest składnikiem klasy) ma dostęp do wszystkich (nawet prywatnych) składników klasy. Funkcja staje się zaprzyjaźniona, gdy jej deklarację wewnątrz klasy poprzedzimy słowem kluczowym friend. Funkcja jest zaprzyjaźniona z klasą, a nie z konkretnym obiektem. Zalety funkcji zaprzyjaźnionych: -funkcja może być przyjacielem więcej niż jednej klasy, -funkcja może dokonywać konwersji zdefiniowanych przez użytkownika na argumentach jej wywołania, -można nadać dostęp do składowych prywatnych nawet funkcjom, które nie mogłyby być składnikami klasy, np. napisanym w innym języku programowania.

22 Funkcje zaprzyjaźnione(2)
Zasady tworzenia funkcji zaprzyjaźnionych: -z wnętrza funkcji zaprzyjaźnionej można się odwoływać do składników przez: obiekt.nazwa lub wsk->nazwa, -w przypadku funkcji przeładowanych przyjacielem klasy K jest tylko ta wersja funkcji, która odpowiada liście argumentów widocznej w deklaracji przyjaźni, -funkcja zaprzyjaźniona może być też funkcją składową innej klasy (friend nazwa_klasy::nazwa_funkcji(int a);), -przyjaźń nie jest przechodnia, -przyjaźń nie jest dziedziczona, -aby klasy miały nawzajem zaprzyjaźnione funkcje, to całe klasy muszą być ze sobą nawzajem zaprzyjaźnione, np.: class K {friend class M; // ... }; Oznacza to, że wszystkie składowe klasy M mają dostęp do prywatnych składników klasy K.

23 Funkcje zaprzyjaźnione(3)
Przykład: class person{ private: char name[30]; char surname[100]; //Deklaracja funkcji zaprzyjaznionej friend void introduce(person pPerson); }; //definicja funkcji zaprzyjaznionej void introduce(person pPerson){ cout<<"My name is "<<pPerson.surname<<endl; cout<<pPerson.name<<" "<<pPerson.surname<<endl;

24 Funkcje zaprzyjaźnione(4)
Ćwiczenie 7. Napisz funkcję zaprzyjaźnioną z klasą PlytaCD zwracającą łączny czas trwania płyt podanych jako argumenty.

25 Przeładowanie operatorów(1)
C++ udostępnia zbiór operatorów umożliwiających operacje na zmiennych typu całkowitego, rzeczywistego i znakowego oraz operatorów indeksowania, wywołania funkcji, dostępu do składowych oraz dynamicznego przydziału, zwalniania pamięci itd. int i, j, k; k = i + j; Większość tych operatorów może zostać zdefiniowana dla operandów innych typów, np.: klasa obiekt1, obiekt2, obiekt3; obiekt3 = obiekt1 + obiekt2; Zdefiniowanie funkcji operatorowej nazywamy przeciążeniem operatora. Identyfikator funkcji ma postać: typ_zwracany (argumenty){...}

26 Przeładowanie operatorów(2)
Lista operatorów, które mogą być przeładowane: + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= = = != <= >= && || , ->* -> new delete () [] Nie mogą być przeładowane operatory: . .* :: ?: Operatory predefiniowane (automatycznie generowane dla każdej klasy): = & , new delete

27 Przeładowanie operatorów(3)
Uwagi: -nie można zmieniać priorytetu wykonywania operatorów, np. wyrażenie a + b * c zawsze jest traktowane jako a + (b * c), a nie jako (a + b) * c, -nie można zmieniać liczby argumentów (tego, czy operator jest jedno-, czy dwuargumentowy), -nie można zmieniać łączności operatorów, np. wyrażenie a=b=c=d niezależnie od sposobu, w jaki przeładowujemy operator odpowiada wyrażeniu a = (b = (c = d)), -jeśli funkcja operatorowa jest zdefiniowana jako zwykła (globalna) funkcja, to przyjmuje tyle argumentów na ilu pracuje operator, -przynajmniej jeden z argumentów musi być typu zdefiniowanego przez użytkownika, -argumenty nie mogą być domniemane,

28 Przeładowanie operatorów(4)
-dana funkcja operatorowa może być albo funkcją globalną, albo funkcją składową klasy, dla której pracuje. Jeśli operator definiujemy jako funkcję składową, to ma ona zawsze o jeden argument mniej niż ta sama funkcja napisana jako globalna, -jeśli chcemy, by operator mógł pracować na niepublicznych składnikach klasy to musimy zadeklarować tę funkcję jako zaprzyjaźnioną z daną klasą, -funkcja operatorowa, która jest funkcją składową klasy – wymaga, aby obiekt stojący po lewej stronie operatora był obiektem jej klasy. Operator, który jest zwykłą funkcją globalną – nie ma takiego ograniczenia.

29 Przeładowanie operatorów(5)
Przeładowanie operatorów jednoargumentowych: -jako zwykła (globalna) funkcja: (K); -jako funkcja składowa klasy K: (void); Przeładowanie operatorów dwuargumentowych: (x, y); (y);

30 Przeładowanie operatorów(6)
Przeładowanie operatorów jako zwykła funkcja: -jeśli operator ma dopuszczać, by po jego lewej stronie stał typ wbudowany, -jeśli operator sięga po obiekt po to, by pracować z nim bez modyfikowania go. Przeładowanie operatorów jako funkcja składowa klasy: -jeśli operator zmienia w jakiś sposób obiekt, na którym pracuje.

31 Przeładowanie operatorów(7)
Dwuargumentowy operator przypisania = klasa &klasa::operator=(klasa &) Służy do przypisania jednemu obiektowi klasy treści drugiego obiektu tej klasy. Operator przypisania składa się zwykle z dwóch części. Najpierw następuje część „destruktorowa”, po czym następuje część „konstruktorowa” – przypominająca konstruktor kopiujący.

32 Przeładowanie operatorów(8)
Przykład: #include <cstdlib> #include <iostream> using namespace std; class Ulamek{ int licznik; int mianownik; public: Ulamek(int l, int m):licznik(l), mianownik(m){}; }; int main(int argc, char *argv[]){ Ulamek a(1,2), b(3,4), c(0, 1), d(1, 1); //Nasze cele to umożliwienie wykonania takich instrukcji c = 1 + a + b - d; cout<< „Wynik=” << c << endl; system("PAUSE"); return EXIT_SUCCESS; }

33 Przeładowanie operatorów(9)
Krok 1 – przeładowanie operatora + W sekcji public klasy Ulamek proszę wstawić deklarację: friend Ulamek operator+(Ulamek a, Ulamek b); Poza klasą proszę wstawić definicję: Ulamek operator+(Ulamek a, Ulamek b){ Ulamek c(0,1); c.licznik = (a.licznik * b.mianownik) + (b.licznik * a.mianownik); c.mianownik = a.mianownik * b.mianownik; return c; }; Proszę przetestować działanie funkcji wykonując instrukcję: c = a + b;

34 Przeładowanie operatorów(10)
Krok 2 – przeładowanie operatora + dla typu int W sekcji public klasy Ulamek proszę wstawić deklarację: friend Ulamek operator+(int a, Ulamek b); Poza klasą proszę wstawić definicję: Ulamek operator+(int a, Ulamek b){ Ulamek c(0,1); c.licznik = b.licznik + a * b.mianownik; c.mianownik = b.mianownik; return c; }; Proszę przetestować działanie funkcji wykonując instrukcję: c = 1 + b;

35 Przeładowanie operatorów(11)
Krok 3 – przeładowanie operatora - W sekcji public klasy Ulamek proszę wstawić deklarację: Ulamek operator-(Ulamek a); Poza klasą proszę wstawić definicję: Ulamek Ulamek::operator-(Ulamek a){ Ulamek c(0,1); c.licznik = (licznik * a.mianownik) - (a.licznik * mianownik); c.mianownik = mianownik * a.mianownik; return c; }; Proszę przetestować działanie funkcji wykonując instrukcję: c = a - b;

36 Przeładowanie operatorów(12)
Krok 4 – przeładowanie operatora << W sekcji public klasy Ulamek proszę wstawić deklarację: friend ostream &operator<<(ostream &out, Ulamek &a); Poza klasą proszę wstawić definicję: ostream &operator<<(ostream &out, Ulamek &a){ out<<a.licznik<<"/"<<a.mianownik; return out; } Proszę przetestować działanie funkcji wykonując instrukcję: cout << a;

37 Przeładowanie operatorów(13)
Ćwiczenie 8: Przeładuj dla klasy Ulamek operator dzielenie dwóch obiektów tej klasy Napisz funkcję globalną realizującą podnoszenie do potęgi obiektów klasy Ulamek Utwórz klasę Osoba posiadającą prywatne składniki: imie, nazwisko i rok urodzenia, a następnie przeładuj dla tej klasy operator << tak, aby możliwe było wypisywanie na ekran obiektów tej klasy za pomocą instrukcji cout<< nazwaObiektu. Napisz klasę Rachunek posiadającą składniki: kwota, waluta. Dodaj do utworzonej klasy konstruktor inicjalizujący wartości składników. Przeładuj operatory dodawania i odejmowania dla utworzonej klasy. Funkcje operatorowe powinny dodawać/odejmować kwoty na rachunku dokonując przeliczenia po ustalonych kursach w przypadku wystąpienia niezgodności waluty.

38 Dziedziczenie (1) Dziedziczenie to technika pozwalająca na definiowanie klasy przy wykorzystaniu klasy już wcześniej istniejącej. Istniejąca klasa (klasa podstawowa): class X { } Nowa klasa (klasa pochodna): class Y : specyfikator_dostępu X

39 Dziedziczenie (2) W klasie pochodnej można zdefiniować:
-dodatkowe dane składowe, -dodatkowe funkcje składowe, -składniki, które już istnieją w klasie podstawowej (najczęściej funkcje). Specyfikator dostępu określa, do której sekcji klasy Y należą elementy klasy X.

40 Dziedziczenie (3) Sposób umieszczenia składników klasy podstawowej w klasie pochodnej : Od strony klasy podstawowej: -składniki z sekcji private są dziedziczone, ale w zakresie klasy pochodnej nie ma do nich bezpośredniego dostępu, -składniki z sekcji protected i public są dostępne bezpośrednio w klasie pochodnej. Od strony klasy pochodnej: -specyfikator dostępu pozwala określić sposób, w jaki klasa pochodna chce odziedziczyć składniki protected i public klasy X, -jeśli separatorem jest public, składniki protected są dziedziczone jako protected, zaś składniki public są dziedziczone jako public, -jeśli separatorem jest protected, składniki public i protected są dziedziczone jako protected, -jeśli separatorem jest private, składniki public i protected są dziedziczone jako private, -separatorem domyślnym jest private,

41 Dziedziczenie (4) Składowa w klasie pochodnej z użyciem separatora
Składowa w klasie podstawowej private protected public Protected

42 Dziedziczenie (5) Dziedziczenie składników z klasy podstawowej nie obejmuje: -konstruktorów, -destruktorów, -operatora przypisania.

43 Dziedziczenie (6) Przykład: class samochod{ int rocznik; public:
samochod(int r):rocznik(r){}; void pokaz(){cout<<"Rocznik: "<<rocznik<<endl;} }; class osobowy: public samochod{ int ilosc_miejsc; osobowy(int m, int r):samochod(r), ilosc_miejsc(m){} void pokaz(){ samochod::pokaz(); cout<<"Ilosc miejsc: "<<ilosc_miejsc<<endl; }

44 Dziedziczenie (7) Dziedziczenie wielokrotne
class A :specyfikator_dostępu B, specyfikator_dostępu C { ... } Jeśli klasy B i C mają składniki o jednakowych nazwach, to można się do nich odwoływać przez: nazwa_klasy::nazwa_skladnika;

45 Dziedziczenie (8) Zadanie 3.
1) Zaimplementuj klasę Pojazd zawierającą składniki reprezentujące: maksymalną prędkość, moc silnika, rodzaj paliwa, ładowność itp.. 2) Dodaj do klasy funkcje składowe setNazwaPola(wartość) oraz funkcjeskładowe getNazwaPola(). Funkcje setNazwaPola powinny umożliwić ustalenie wartości składników, a funkcja getNazwaPola pobranie ich wartości. 3) Na podstawie klasy Pojazd utwórz klasy pochodne Samolot, Samochod, Czolg. Dodaj po kilka składników do każdej klasy pochodnej. 4) Na podstawie klasy Samochod utwórz klasy pochodne Fiat i Ford. 5) Utwórz klasę Statek zawierającą składniki reprezentujące: wyporność, maksymalną prędkość, rodzaj paliwa itp.. 6) Na podstawie klas Pojazd i Statek utwórz klasę Amfibia. 7) Do klas Pojazd i Statek dodaj konstruktory uzupełniające dane obiektów. 8) Dodaj konstruktory do utworzonych klas pochodnych. 9) Stwórz obiekty klasy Pojazd, Samolot, Samochod, Statek i Amfibia. Dla utworzonych obiektów sprawdź działanie funkcji składowych setNazwaPola i getNazwaPola. W klasach pochodnych utwórz funkcje getNazwaPola i setNazwaPola realizujące zadania podobne jak w klasach podstawowych, ale obejmujące też składniki specyficzne dla danych klas.

46 Wskaźniki (1) Przypomnienie Definiowanie wskaźników: typ *nazwa_wsk;
Ustawianie wskaźnika na obiekt: nazwa_wsk = &k; Odwołanie do wskazywanej wartości: *nazwa_wsk Obszary zastosowania wskaźników: praca z tablicami, funkcje, które mogą zmieniać wartość przesyłanych do nich argumentów, dostęp do specjalnych komórek pamięci, rezerwacja obszarów pamięci Szerzej: Jerzy Grębosz, Symfonia C++, s

47 Funkcje wirtualne (1) Ćwiczenia:
Utwórz klasę Auto posiadającą funkcję opis() wypisującą na ekran tekst „Auto”. Utwórz klasy Osobowy, Ciężarowy, Autobus dziedziczące z klasy Auto. W klasach pochodnych przeładuj funkcję opis() tak, aby w każdej klasie wypisywała na ekran inny tekst. Utwórz obiekty każdej z utworzonych klas i wywołaj ich metody opis(). Utwórz wskaźnik do obiektu klasy auto(), ustaw go kolejno tak, aby wskazywał na obiekty klas pochodnych i uruchom za każdym razem metodę opis() korzystając z tego wskaźnika (wskaznik -> opis();). Zaobserwuj działanie programu, a następnie zmodyfikuj deklarację metody opis tak, aby zawierała słowo kluczowe virtual: void virtual opis(){...} 7. Ponownie uruchom program i porównaj działanie z wersją bez słowa kluczowego virtual.

48 Praca z plikami (1) Ćwiczenia: Przepisz i uruchom poniższy program:
#include <cstdlib> #include <iostream> #include <fstream> using namespace std; class station{ public: int No; char name[40]; char changes[100]; void showName(){ cout<<name<<endl; }; void showChanges(){ cout<<"Changes: "<<changes<<endl; int main(int argc, char *argv[]) { station route1[20]; int i, j; char tempNo[10]; i = 0;

49 Praca z plikami (2) //1) definicja strumienia ifstream route1File;
//2) Wskazanie, z ktorym plikiem ma sie komunikowac strumien route1File.open("route1.txt"); if(!route1File){ cout<<"Couldn't open file!"<<endl; system("PAUSE"); return 1; } //3) Operacje wejscia/wyjscia while(route1File){ route1File>>route1[i].name; route1File>>route1[i].No; route1File>>route1[i].changes; i++; }; for(j = 0; j<i-1; j++){ cout<<"Station no "<<route1[j].No<<": "; route1[j].showName(); route1[j].showChanges(); //4) Zakonczenie pracy z plikiem route1File.close();

50 Praca z plikami (3) Utwórz plik route1.txt, umieść go w katalogu, w którym znajduje się program i zapisz w nim dane: Worcester 1 Birmingham,London Reading 2 Edingburg,London Oxford 3 London,Birmingham London 4 Liverpool,Birmingham,Glasgow 3. Uruchom program i zaobserwuj jego działanie.

51 Praca z plikami (4) Funkcja open()
void open(char* nazwa_pliku, int tryb = open_mode, int prot = filebuf::openprot); open_mode przyjmuje domyślne wartości: - w klasie ifstream ios::in, - w klasie ofstream ios::out. Możliwe wartości trybu otwarcia: in – otwarcie do czytania, out – otwarcie do zapisu, ate – otwarcie z ustawieniem na końcu zawartości, app – otwarcie do dopisywania, trunc – otwarcie z kasowaniem ewentualnej starej zawartości, nocreate – otwarcie pod warunkiem, że plik już istnieje, noreplace – otwarcie pod warunkiem, że plik nie istnieje, binary – otwarcie w trybie binarnym

52 Konwersje (1) Ćwiczenia:
Utwórz klasę Ulamek(), zawierającą składniki reprezentujące licznik oraz mianownik. Napisz funkcję Ulamek dodaj(Ulamek p1, Ulamek p2) realizującą dodawanie ułamków. Sprawdź działanie utworzonej funkcji na obiektach klasy Ulamek. Zastanów się jak zmodyfikować program, aby możliwe było wywołanie funkcji dodaj z parametrami typu całkowitego. Utwórz konstruktor, Ulamek::Ulamek(int p1){ licznik = p1; mianownik = 1; } Wywołaj metodę dodaj z parametrem będącym liczbą całkowitą i zaobserwuj działanie. Zamieść w programie poniższą instrukcję i spróbuj go uruchomić: cout<<obiektKlasyUlamek<<endl; Dodaj do klasy ulamek poniższą funkcję konwertującą i ponownie uruchom program: operator float(){return float(licznik) / mianownik;}

53 Konwersje (2) Sposoby definiowania konwersji typu A na typ B:
Konstruktor klasy B przyjmujący jako argument obiekt klasy A Funkcja składowa klasy A zwana funkcją konwertującą. Funkcja konwertująca to funkcja składowa klasy A: A::operator T() gdzie T oznacza nazwę typu, na który chcemy dokonać konwersji. Uwagi a) Funkcja konwertująca musi być funkcją składową klasy. b) Funkcja nie określenia zwracanego typu. c) Funkcja ma pustą listę argumentów.

54 Debugowanie (1) Debugowanie w środowisku Dev C++
Wykorzystanie opcji debugowania w środowisku Dev C++ wymaga odpowiedniej konfiguracji Linkera. Po wyborze pozycji menu „Project\Project Options” należy przejść na zakładkę Compiler, a następnie po wybraniu opcji Linker ustawić na „Yes” wartość parametru „Generate debug information". Dev C++ udostępnia kilka opcji pomocnych w debugowaniu kodu. Wszystkie dostępne są w menu Debug.

55 Debugowanie (2) Ćwiczenie
Otwórz dowolny program zrealizowany na poprzednich zajęciach. Wykonaj program w dotychczasowy sposób (Execute\Compile & Run). Ustaw opcje kompilatora jak opisano na poprzednim slajdzie. Ustaw kursor na początku funkcji main i wybierz opcję „Debug\Toggle breakpoint”. Wybierz opcję „Debug\Run to cursor”. Rozpoczęło się wykonanie programu, jednak zostało ono zatrzymane na linii, w której ustalono breakpoint. Skorzystaj z opcji „Debug\Next step”. W ten sposób można przejść do wykonania kolejnej instrukcji. Ustaw breakpoint w dalszej linii i wykorzystaj opcję „Debug\Continue”. Ustaw breakpoint na wywołaniu własnej funkcji, a gdy sterowanie przejdzie do tej lini skorzystaj z opcji „Debug\Step into”.

56 Debugowanie (3) Ćwiczenie
Wybierz opcję „Debug\Add Watch” i wpisz po pojawiającym się okienku nazwę zmiennej wykorzystywanej w programie. Skorzystaj z opcji „Debug\Watch Variables”. W ten sposób można zobaczyć jaką wartość przyjmuje w danym momencie wykonywania programu zmienna. Dodaj do funkcji main instrukcję „cout << argv[1]<<endl;” (argv jest drugim parametrem funkcji main). W okienku „Debug\Parameters” wpisz w górnym polu jakąś wartość i zaobserwuj wynik działania programu. Tabela dostępna w drugim parametrze funkcji main przechowuje parametry przekazywane przy wywołaniu programu z linii komend.

57 Wyjątki (1) Wystąpienie w programie nieoczekiwanej sytuacji, powinno być zasygnalizowane przez programistę. Dotychczas rozwiązywane to było np. przez zwrócenie specyficznej wartości, co nie było najlepszym rozwiązaniem, bo sygnał musiał być taki jak wartość zwracana przez funkcję. Lepszym rozwiązaniem jest korzystanie z mechanizmu obsługi wyjątków. Szkielet obsługi wyjątków try { fun(); fun2(); //podejrzane funkcje } catch(char obj) //akcje wykonywane w przypadku wystapienia bledu

58 Wyjątki (2) W instrukcji catch definiujemy typ wyjątku. Nazwa obiektu nie jest konieczna, ale chcąc poznać jego wartość trzeba go nazwać. Można stworzyć kilka bloków catch, w zależności od tego, ile możliwych typów zamierzamy przechwycić. Rzucając wyjątek konkretnego typu jest on obsługiwany przez pierwszy blok catch nawet jeżeli inne nadają się lepiej (analogicznie do instrukcji if else). Rozsądne jest często zabezpieczenie się blokiem przechwytującym dowolne wyjątki: catch(...) Dobrą praktyką jest zaznaczanie jakie wyjątki może generować funkcja, np.: void funkcja(int a) throw(char) Zapis oznacza, że funkcja może zwrócić wyjątek typu char.

59 Wyjątki (3) Definiowanie własnych wyjątków Przykład
#include <stdexcept> class DivideByZeroException : public runtime_error { public: // konstruktor ustala domyslny komunikat DivideByZeroException::DivideByZeroException() : runtime_error( "dzielenie przez 0" ) {} };

60 Wyjątki (4) Rzucanie wyjątku
W ciele funkcji możemy zasygnalizować wystąpienie wyjątku. Przykład double divide(double a, double b){ if(b == 0) throw DivideByZeroException(); //przerwanie wykonania funkcji //lancuch znakow trafia do bloku //catch return a / b; }

61 Wyjątki (5) Przykład double result, number1 = 10, number2 = 0; try{
result = divide( number1, number2 ); cout << "Iloraz = " << result << endl; } // przechwycenie wyjatku dzielenia przez 0 catch ( DivideByZeroException &divideByZeroException ){ cout << "Wystapil wyjatek: " << divideByZeroException.what() << endl;

62 Wyjątki (6) Ćwiczenie Utwórz klasę „Kontener” posiadającą prywatny składnik „Tab” będący 20-elementową tablicą liczb zmiennoprzecinkowych. Dodaj do klasy „Kontener” publiczną metodą SetIthElement do ustawiania wartości elementów tablicy „Tab” Utwórz klasę reprezentującą wyjątek występujący przy podaniu niecałkowitego indeksu tabeli Utwórz klasę reprezentującą wyjątek występujący przy podaniu indeksu tabeli spoza dostępnego zakresu Przechwyć utworzone wyjątki w SetIthElement i zaprezentuj działanie tej metody na przykładzie

63 Szablony funkcji (1) Za pomocą szablonów funkcji możliwe jest stworzenie wielu funkcji różniących się tylko typem przyjmowanych argumentów. Przykładowo chcąc stworzyć funkcję print, wypisującą na ekran parametry różnych typów, można skorzystać z instrukcji: void print(char a) { cout<<a; } void print(double a) void print(int a)

64 Szablony funkcji (2) Szablony funkcji pozwalają jednak wskazać kompilatorowi sposób na tworzenie samodzielnie takich funkcji: template<class typ> void print(typ a) { cout<<a; }

65 Szablony funkcji (3) Przykład #include <cstdlib>
#include <iostream> using namespace std; template<class type> type bigger(type a, type b) { return (a > b)? a : b; } int main(int argc, char *argv[]) int a = 10, b = 20; double x = 10.1, y = 20.2; unsigned long la = , lb = 345; cout << "bigger int:" <<bigger(a, b)<<endl; cout << "bigger double:" <<bigger(x, y)<<endl; cout << "bigger long:" <<bigger(la, lb)<<endl; cout << "bigger ASCII char:" <<bigger('L', 'Y')<<endl; system("PAUSE"); return EXIT_SUCCESS;

66 Szablony funkcji (4) Ćwiczenie
Napisz i wykorzystaj w programie szablon funkcji wypisującej na ekran rozmiar parametru.

67 Szablony klas (1) Załóżmy, że potrzebujemy zdefiniować klasy PointInt, posiadające 3 współrzędne: class PointInt { public: PointInt( int _x, int _y, int _z ): x(_x), y(_y), z(_x){ } int x, y, z; }; Chcąc zdefiniować analogiczne klasy ze współrzędnymi innych typów, musielibyśmy skopiować i zmodyfikować odpowiednio powyższy kod. Zadanie to można też wykonać za pomocą szablonów klas.

68 Szablony klas (2) Przykład template <class Type> class Point {
public: Point( Type _x, Type _y, Type _z ): x(_x), y(_y), z(_x) { } Type x, y, z; }; int main(void) Point <int> A(0,-10,0); Point <unsigned> B(0,10,5); cout << "A(" << A.x << "," << A.y << "," << A.z << ")" << endl; cout << "B(" << B.x << "," << B.y << "," << B.z << ")" << endl; }

69 Szablony klas (3) Ćwiczenie
Napisz i wykorzystaj w programie szablon klasy posiadający składnik będący tablicą obiektów typu pierwszego parametru szablonu i liczbie elementów równej drugiemu parametrowi. Klasa powinna też zawierać funkcję zwracającą rozmiar tej tablicy.

70 Standard Template Library (1)
Standard Template Library, STL (ang. standardowa biblioteka szablonów) – biblioteka C++ zawierająca algorytmy, pojemniki, iteratory oraz inne konstrukcje w formie szablonów, gotowe do użycia w programach. STL jest to tzw. biblioteka generyczna, co oznacza, że jej składniki współpracują równie dobrze z typami wbudowanymi w język, z typami wbudowanymi w bibliotekę, co z typami zdefiniowanymi przez użytkownika, pod warunkiem, że spełniają pewne określone warunki. Dokumentacja:

71 Standard Template Library (2)
Klasa string Przykład #include <cstdlib> #include <iostream> #include <string> using namespace std; int main(){ string punkt1; punkt1 = "1. Przypisanie wartosc zmiennej klasy string"; punkt1 += "."; string odstep(60,'-'); string punkt2( "2. Zmienna klasy string utworzona za pomoca konstruktora." ); string punkt3 = "3. Inicjalizacja wartosci zmiennej klasy string."; cout << odstep << endl << punkt1 << endl << punkt2 << endl << punkt3 << endl << odstep << endl; system("PAUSE"); return 0; } Ćwiczenie Napisz program zapisujący w zmiennej string tekst wpisany przez użytkownika, a następnie wypisujący go na ekran w odwróconej kolejności.

72 Standard Template Library (3)
Pojemniki w STL Pojemnik to obiekt, który może przechowywać obiekty innej klasy i zarządzać nimi. Pojemniki sekwencyjne pozwalają na dotarcie do poszczególnych obiektów przez podanie ich numerów. Wadą pojemników sekwencyjnych jest liniowa zależność czasu operacji wpisania obiektu do pojemnika od odległości do końca pojemnika. Przykładem pojemnika sekwencyjnego jest wektor. Pojemnik pośredni przechowuje nie obiekty, lecz wskaźniki do nich. Taki pojemnik lepiej nadaje się do przechowywania dużych obiektów oraz umożliwia przechowywanie tego samego obiektu w wielu pojemnikach. Dodatkowo może przechowywać obiekty klas pochodnych. Pojemniki kojarzące umożliwiają szybkie odszukanie obiektu na podstawie klucza. Jest to pewne uogólnienie pojemników sekwencyjnych, w którym klucz nie musi być liczbą naturalną.

73 Standard Template Library (4)
Klasa vector Przykład #include <iostream> #include <vector> #include <string> #include <algorithm> #include <iterator> using namespace std; int main(){ vector<string> sentence; // tworzenie pustego wektora obiektow klasy string // dodanie elementow sentence.push_back("Raz"); sentence.push_back("Dwa"); sentence.push_back("Trzy"); // wypisanie elementow oddzielonych spacjami copy (sentence.begin(), sentence.end(), ostream_iterator<string>(cout," ")); cout << endl; swap (sentence[0], sentence[2]); // zamiana elementow wektora sentence.back() = "Jeden"; // przypisanie wyrazu „jeden" do ostatniego elementu sentence.push_back("Zero"); // wstawienie elementu "zero" na koncu wektora // informacje o wektorze cout << " max_size(): " << sentence.max_size() << endl; cout << " size(): " << sentence.size() << endl; cout << " capacity(): " << sentence.capacity() << endl; system("PAUSE"); }

74 Standard Template Library (5)
Ćwiczenie 1) Napisz program pobierający z klawiatury kilka wyrazów zapisując je w wektorze obiektów klasy string, a następnie usuwający pierwsze znaki z wprowadzonych wyrazów.

75 Standard Template Library (6)
Klasa list Przykład #include <iostream> #include <list> using namespace std; int main(){ list<char> alfabet; // lista znakow // dolaczanie do listy znakow od a do z for (char c='a'; c<='z'; ++c) { alfabet.push_back(c); } //wypisywanie zawartosci listy //Jak dlugo sa elementy wypisywany, a nastepnie usuwany jest pierwszy element while (! alfabet.empty()) { cout << alfabet.front() << " "; alfabet.pop_front(); cout << endl; system("PAUSE");

76 Standard Template Library (7)
Ćwiczenie Zmodyfikuj przykładowy program tak, aby alfabet został wyświetlony od końca Przed wyświetleniem alfabetu sprawdź i wypisz na ekran liczbę elementów listy.

77 Standard Template Library (8)
Klasa map Przykład #include <iostream> #include <map> #include <string> using namespace std; int main() { map<string, string> dictionary; dictionary["outclass"] = "zdeklasowac"; dictionary["bound"] = "zobowiazany"; dictionary["indulgence"] = "poblazliwosc"; dictionary["bluntness"] = "bezceremonialnosc"; dictionary["superstition"] = "zabobon"; cout << "dictionary[outclass]=" << dictionary["outclass"] << endl << endl; cout << "Liczba elementow: " << dictionary.size() << endl; for( map<string,string>::iterator ii=dictionary.begin(); ii!=dictionary.end(); ++ii) cout << (*ii).first << ": " << (*ii).second << endl; } system("PAUSE");

78 Standard Template Library (9)
Ćwiczenie Napisz program przechowujący w pojemniku map kody kreskowe produktów oraz ich ceny. Dodaj kilka par kod-cena. Użytkownik wpisując kod kreskowy produktu powinien zobaczyć jego cenę oraz cenę sumaryczną

79 Standard Template Library (10)
Algorytmy standardowej biblioteki szablonów: accumulate() adjacent_difference() adjacent_find() binary_search() copy() copy_backward() copy_n() count() count_if() equal() equal_range() fill() fill_n() find() find_end() find_first_of() find_if() for_each() generate() generate_n() includes() inner_product() inplace_merge() iota() is_heap() is_sorted() iter_swap() lexicographical_compare() lexicographical_compare_3way() lower_bound() make_heap() max() max_element() merge() min() min_element() mismatch() next_permutation() nth_element() partial_sort() partial_sort_copy() partial_sum() partition() pop_heap() power() prev_permutation() random_sample() random_sample_n() random_shuffle() remove() remove_copy() remove_copy_if() remove_if() replace() replace_copy() replace_copy_if() replace_if() reverse() reverse_copy() rotate() rotate_copy() search() search_n() set_difference() set_intersection() set_symmetric_difference() set_union() sort() sort_heap() stable_partition() stable_sort() swap() swap_ranges() transform() unique() unique_copy() upper_bound()

80 Standard Template Library (11)
Przykład: #include <cstdlib> #include <iostream> #include <vector> using namespace std; int main(int argc, char *argv[]) { vector<int> v; v.push_back( 1410 ); v.push_back( 966 ); v.push_back( 1683 ); v.push_back( 1989 ); cout << "Oryginalny porzadek: "; for( int i = 0; i < v.size(); ++i ) { cout << v[i] << " "; } sort( v.begin(), v.end() ); cout << endl << "Posortowane: "; cout << endl; system("PAUSE"); return EXIT_SUCCESS;

81 Standard Template Library (12)
Ćwiczenie Napisz program wykorzystujący bibliotekę STL, który pobiera od użytkownika współrzędne dwóch wektorów i wypisuje na ekran ich iloczyn skalarny (inner product) (+) Korzystając z odpowiedniego algorytmu STL napisz program pobierający od użytkownika dwa ciągi znaków, których wartości są następnie zamienione, a wartości wypisane ponownie na ekran (+/2)

82 Składniki statyczne (1)
Dane statyczne są tworzone w pamięci jednokrotnie i są wspólna dla wszystkich egzemplarzy obiektów danej klasy. Dane istnieją nawet wtedy, gdy nie istnieje żaden element danej klasy. Przykłady deklaracji składników statycznych: static int skladnik; static void funkcja(); Definicja składnika statystycznego musi mieć zakres pliku. Należy je zdefiniować poza wszelkimi funkcjami i klasami: int klasa::skladnik; Odwołanie do składników statycznych: nazwa_klasy::skladnik = 1; nazwa_klasy::funkcja();

83 Składniki statyczne (2)
Ćwiczenie Napisz klasę pionek posiadającą składniki opisujące położenie na szachownicy. Dodaj statyczny składnik określający liczbę istniejących obiektów. Utwórz destruktor zmniejszający składnik statyczny o 1 oraz konstruktor zwiększający ten składnik o 1. Zaprezentuj działanie klasy na przykładzie

84 Tablice obiektów (1) Tworzenie obiektów
nazwa_klasy nazwa_tablicy[rozmiar]; Odwołanie do i-tego obiektu z tablicy nazwa_tablicy[i-1] Odwołanie do składników elementu tablicy nazwa_tablicy[i].skladnik nazwa_tablicy[i].funkcja() Odwołanie do składników elementów tablicy za pomocą wskaźników nazwa_klasy *wsk; wsk = &nazwa_tablicy[i]; wsk->skladnik;

85 Tablice obiektów (2) Inicjalizacja tablic obiektów
Agregaty – klasy, której wszystkie składniki są public oraz nie ma konstruktorów i destruktorów Przykład class Punkt{ public: int x; int y; int z; } ... Punkt figura[10] = {10, 20, 30, 0,0,0, 100,200,300};

86 Tablice obiektów (3) Inicjalizacja tablic obiektów Nie agregaty
Przykład class Punkt{ int x; int y; int z; public: Punkt(int px, int py, int pz): x(px), y(py), z(pz){}; } ... Punkt figura[10] = { Punkt(10,20,30), Punkt(0,0,0), Punkt(100,200,300) };

87 Tablice obiektów (4) Inicjalizacja tablic obiektów
Tablice tworzone w zapasie pamięci W zapasie pamięci można tworzyć tablice obiektów klas, które mają konstruktor domniemany albo nie mają żadnych konstruktorów Przykład class Punkt{ int x; int y; int z; } ... Punkt *wsk; wsk = new Punkt[10];

88 Tablice obiektów (4) Ćwiczenie
Utwórz klasę z Konto publicznymi składnikami numer konta, waluta oraz kwota na koncie, Utwórz 10 elementową tablicę obiektów klasy Konto i zainicjalizuj jej wartości 3) Dodaj do klasy Konto konstruktor inicjalizujący wartości składników i utwórz 4 elementową tablicę obiektów klasy Konto

89 Namespace Namespace pozwala grupować zbiór globalnych klas, obiektów i funkcji. Pozwala wydzielić z zasięgu globalnego jego podzbiór znany pod nazwą namespace. Przykład: #include <iostream.h> namespace first { int var = 5; } namespace second { double var = ; } int main () { cout << first::var << endl; cout << second::var << endl; return 0; }

90 Namespace Using namespace nazwa sprawia, że obiekty i funkcje wskazanej namespace mogą być dostępne bezpośrednio: #include <iostream.h> namespace first { int var = 5; } namespace second { double var = ; } int main () { using namespace second; cout << var << endl; cout << (var*2) << endl; return 0; }


Pobierz ppt "Zasady zaliczenia Warunki uzyskania zaliczenia:"

Podobne prezentacje


Reklamy Google