Programowanie w C++ Wykład 8 Katarzyna Grzelak 15 kwietnia 2019 K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33
Klasy - powtórzenie Klasy typy definiowane przez użytkownika Klasy zawieraja dane składowe plus funkcje składowe (metody) K.Grzelak (Wykład 8) Programowanie w C++ 2 / 33
Podział na pliki.h i.cc Każda klasa w osobnym pliku (na ogół) W pliku nagłówkowym (rozszerzenie.h) definicja klasy W pliku.cc (lub.cpp,.cxx... ) definicje funkcji składowych K.Grzelak (Wykład 8) Programowanie w C++ 3 / 33
Plik nagłówkowy z definicja klasy Średnik na końcu! Przykład: Wektor2D.h #ifndef WEKTOR2D_H #define WEKTOR2D_H class Wektor2D { public: void ustaw(double a1, double b1, double a2, double b2); double dlugosc(); private: double x1,y1,x2,y2; }; #endif K.Grzelak (Wykład 8) Programowanie w C++ 4 / 33
Plik z definicjami funkcji składowych Przykład: Wektor2D.cc #include<cmath> #include "Wektor2D.h" void Wektor2D::ustaw(double a1, double b1, double a2, double b2){ x1=a1; y1=b1; x2=a2; y2=b2; } double Wektor2D::dlugosc(){ double d=sqrt((x2-x1)*(x2-x1) +(y2-y1)*(y2-y1)); return d; } K.Grzelak (Wykład 8) Programowanie w C++ 5 / 33
Enkapsulacja Enkapsulacja - ukrycie wewnętrznej struktury Dane składowe zwykle deklarowane jako prywatne; dostęp do nich tylko za pomoca funkcji składowych. Konsekwencje enkapsulacji Program używajacy danej klasy nie musi znać jej struktury danych Można przebudować klasę, a użycie będzie niezmienione (jeśli prototypy funkcji składowych będa niezmienione) K.Grzelak (Wykład 8) Programowanie w C++ 6 / 33
Główny program, użycie nowego typu zmiennej Przykład: prog.cc #include<iostream> #include "Wektor2D.h" using namespace std; int main(){ Wektor2D v1; v1.ustaw(0.5,0.2,1.5,0.8); cout «v1.dlugosc() «endl; return 0; } K.Grzelak (Wykład 8) Programowanie w C++ 7 / 33
Podział na pliki.h i.cc Dlaczego klasy zapisuje się w oddzielnych plikach? Tej samej klasy można łatwo używać w wielu miejscach Każda klasę kompiluje się tylko raz (szczególnie ważne w dużych projektach) K.Grzelak (Wykład 8) Programowanie w C++ 8 / 33
Kompilacja programu zapisanego w kilku plikach Gdy program złożony z niewielkiej liczby plików: g++ -o prog prog.cc Wektor2D.cc Pliki nagłówkowe właczane automatycznie przez preprocesor (polecenie #include wewnatrz plików.cc) Większe projekty proces kompilacji zapisany w pliku Makefile (więcej na jednym z następnych wykładów); środowiska do kompilacji K.Grzelak (Wykład 8) Programowanie w C++ 9 / 33
Użycie nowego typu Deklaracja zmiennej typu Wektor2D: Wektor2D v1; Przekazywanie obiektu typu Wektor2D do funkcji jak w przypadku zwykłych typów i vector a STL przez wartość (niedobre rozwiazanie gdy duży obiekt): void (Wektor2D v1); przez referencję (jeśli funkcja ma zmieniać obiekt): void (Wektor2D &v1); przez referencję (jeśli funkcja ma nie zmieniać obiektu): void (const Wektor2D &v1); K.Grzelak (Wykład 8) Programowanie w C++ 10 / 33
Konstruktor, czyli rozbudowujemy klasę Konstruktor czyli powołanie do życia obiektu i nadanie wartości danym składowym w jednej linijce Tak można zrobić przy użyciu funkcji składowej... Wektor2D v1; v1.ustaw(0.5,0.2,1.5,0.8);... ale tak byłoby prościej: Wektor2D v1(0.5,0.2,1.5,0.8); K.Grzelak (Wykład 8) Programowanie w C++ 11 / 33
Konstruktor Konstruktor to specjalna funkcja składowa wywoływana automatycznie przy tworzeniu obiektu. Konstruktor nazywa się tak samo jak klasa Przed nazwa nie ma żadnego typu wartości zwracanej; nie ma return Konstruktorów może być kilka (z różnymi argumentami) K.Grzelak (Wykład 8) Programowanie w C++ 12 / 33
Konstruktor Przykłady konstruktorów klasy Wektor2D // Konstruktor standardowy Wektor2D(){} // Drugi konstruktor Wektor2D(double a1, double b1, double a2, double b2){ x1=a1; y1=b1; x2=a2; y2=b2; } K.Grzelak (Wykład 8) Programowanie w C++ 13 / 33
Konstruktor Przykłady konstruktorów klasy Wektor2D // Konstruktor standardowy Wektor2D(){} // Inny zapis konstruktora // z poprzedniej klasy // (prawie równoważny) Wektor2D(double a1,double b1,double a2,double b2): x1(a1),y1(b1),x2(a2),y2(b2) { } W definicji klasy może nie być konstruktora konstruktor standardowy zostanie stworzony automatycznie. K.Grzelak (Wykład 8) Programowanie w C++ 14 / 33
Cały plik nagłówkowy z konstruktorami #ifndef WEKTOR2D_H #define WEKTOR2D_H class Wektor2D { public: Wektor2D(){} // konstruktor standardowy Wektor2D(double a1,double b1,double a2,double b2): x1(a1),y1(b1),x2(a2),y2(b2) { } // drugi // konstruktor void ustaw(double a1, double b1, double a2, double b2); double dlugosc(); private: double x1,y1,x2,y2; }; #endif K.Grzelak (Wykład 8) Programowanie w C++ 15 / 33
Konstruktor - użycie // Tutaj zostanie uruchomiony // standardowy konstruktor Wektor2D v1; v1.ustaw(0.5,0.2,1.5,0.8); // Tutaj zostanie uruchomiony drugi // konstruktor Wektor2D v1(0.5,0.2,1.5,0.8); K.Grzelak (Wykład 8) Programowanie w C++ 16 / 33
Konstruktor standardowy (domyślny) - default constructor Standardowy konstruktor, to taki który nie ma żadnych argumentów (albo wszystkie argumenty maja domyślne wartości) Jeśli nie stworzymy żadnego konstruktora, to konstruktor standardowy zostanie stworzony automatycznie K.Grzelak (Wykład 8) Programowanie w C++ 17 / 33
Konstruktor standardowy (domyślny) - default constructor Konstruktor standardowy Trzy możliwości: nie tworzymy żadnego konstruktora konstruktor standardowy zostanie stworzony automatycznie tworzymy własny konstruktor standardowy i ten jest używany tworzymy własne konstruktory (z różnymi argumentami), ale między nimi nie ma tego standardowego (bez żadnych argumentów) klasa nie ma konstruktora standardowego i nie można stworzyć obiektu bez podawania żadnego argumentu (np. NazwaKlasy kl;) K.Grzelak (Wykład 8) Programowanie w C++ 18 / 33
Konstruktor domyślny w standardzie C++11 Konstruktor standardowy Tak można zrobić zawsze: NazwaKlasy(); A dodatkowo tak w standardzie C++11: NazwaKlasy()=default; Standardowy konstruktor zostanie stworzony, nawet jeśli sa inne konstruktory. NazwaKlasy()=delete; Nie można stworzyć obiektu bez podawania żadnego argumentu ( np: NazwaKlasy kl;) Program się nie skompiluje. K.Grzelak (Wykład 8) Programowanie w C++ 19 / 33
Destruktor Destruktor to specjalna funkcja składowa wywoływana automatycznie przed likwidacja obiektu. Destruktor nazywa się tak samo jak klasa + falka przed nazwa. Przed nazwa nie ma żadnego typu wartości zwracanej; nie ma return W definicji klasy może nie być destruktora. K.Grzelak (Wykład 8) Programowanie w C++ 20 / 33
Cały plik nagłówkowy z konstruktorami i destruktorem #ifndef WEKTOR2D_H #define WEKTOR2D_H class Wektor2D { public: Wektor2D(){} // konstruktor standardowy // drugi konstruktor Wektor2D(double a1,double b1,double a2,double b2): x1(a1),y1(b1),x2(a2),y2(b2) { } Wektor2D() { } // destruktor void ustaw(double a1, double b1, double a2, double b2); double dlugosc(); private: double x1,y1,x2,y2; }; #endif K.Grzelak (Wykład 8) Programowanie w C++ 21 / 33
Wybrane klasy z biblioteki standardowej klasa string K.Grzelak (Wykład 8) Programowanie w C++ 22 / 33
Klasa string - konstruktory #include<string> Pusty string, użyty standardowy konstruktor: string wyraz; string = Ala ma kota ; Inicjalizacja stringu (konstruktor niestandardowy): string napis1( Ala ma kota ); char tab[20]={ Ala ma psa }; string napis2(tab); K.Grzelak (Wykład 8) Programowanie w C++ 23 / 33
Klasa string - funkcje składowe size() z ilu znaków składa się string empty() zwraca true, jeśli string jest pusty clear() - kasuje zawartosc obiektu at(pozycja), [pozycja] odniesienie do znaku znajdujacego się na pozycji pozycja c_str() zamiana obiektu z klasy string na c-string... K.Grzelak (Wykład 8) Programowanie w C++ 24 / 33
Wybrane klasy z biblioteki standardowej o strumieniach Wprowadzanie i wyprowadzanie informacji strumień bajtów płynacy od źródła do ujścia. K.Grzelak (Wykład 8) Programowanie w C++ 25 / 33
Strumienie 1 Standardowe strumienie wejściowe i wyjściowe (klawiatura, ekran) 2 Strumienie zwiazane z plikami 3 Strumienie zapisujace do/czytajace z obiektu string K.Grzelak (Wykład 8) Programowanie w C++ 26 / 33
Pliki Pamiec glowna Pamiec zewnetrzna File buffer Write Read File K.Grzelak (Wykład 8) Programowanie w C++ 27 / 33
Pliki Plik nagłówkowy #include<fstream> ifstream - klasa do czytania z pliku ofstream - klasa do pisania do pliku K.Grzelak (Wykład 8) Programowanie w C++ 28 / 33
Klasa ofstream - do pisania do plików #include<fstream> Otwieranie pliku do pisania (jeśli istniał, zostanie skasowany): ofstream fileout; fileout.open( out.txt ); lub ofstream fileout( out.txt ); Dopisywanie do końca pliku: ofstream fileout( out.txt,ios::app); K.Grzelak (Wykład 8) Programowanie w C++ 29 / 33
Klasa ofstream - do pisania do plików Analogicznie do cout: ofstream fileout( out.txt ); fileout «Tekst «endl; fileout «M_PI ««M_PI*M_PI «endl; fileout.close(); K.Grzelak (Wykład 8) Programowanie w C++ 30 / 33
Klasa ifstream - do czytania z plików #include<fstream> Otwieranie pliku do czytania: ifstream fileinp; fileinp.open( data.txt ); lub ifstream fileinp( data.txt ); Zaraz za otwarciem sprawdzanie czy plik nie istnieje: if(fileinp.fail()){ cout «Plik nie istnieje «endl; } lub if(!fileinp) { cout «Plik nie istnieje «endl; } K.Grzelak (Wykład 8) Programowanie w C++ 31 / 33
Klasa ifstream - do czytania z plików Nazwa pliku wczytywana z klawiatury: cout «Podaj nazwe pliku «endl; string nazwa; cin» nazwa; ifstream fileinp(nazwa.c_str()); K.Grzelak (Wykład 8) Programowanie w C++ 32 / 33
Klasa ifstream - do czytania z plików Analogicznie do cin: int liczba; while(true){ fileinp» liczba; if(!fileinp){ break; } cout «Wczytana liczba = «liczba «endl; } lub while(fileinp» liczba){ cout «Wczytana liczba = «liczba «endl; } K.Grzelak (Wykład 8) Programowanie w C++ 33 / 33