1 Obiekty,dziedziczenie, Katedra Mechaniki i Inżynierskich Programowanie C++ Obiekty,dziedziczenie, polimorfizm, funkcje wirtualne i wiele innych rzeczy Iwona Adamiec-Wójcik Katedra Mechaniki i Inżynierskich Metod Komputerowych Politechnika Łódzka Filia Bielsko-Biała Programowanie C++
2 Trochę historii... W późnych latach 60-tych i na początku lat 70-tych Dennis Ritchie stworzył język C. W tym czasie A&AT Bell Labs zajmowało się systemem operacyjnym UNIX, który początkowo był tworzony w assemblerze. C był pomyślany jako język wyższego poziomu do programowania systemów operacyjnych. Poprzednik języka C, z którego Ritchie zaczerpnął wiele elementów nazywał się B. W 1985 Bjarne Stroustrup również w Bell Labs stworzył język C++, poszerzając język C o abstrakcyjne typy danych i programowanie obiektowe... Nazwa języka pochodzi od operatora inkrementacji z języka C (++), i oznacza, że język ten nie jest następcą C (w tym przypadku nazywałby się D) a tylko jego rozszerzeniem. Programowanie C++
3 Jeśli chcesz dowiedzieć się trochę więcej... Jeśli chcesz dowiedzieć się trochę więcej... Literatura dostępna w naszej czytelni: Jerzy Grębosz: Symfonia C++ Bjarne Stroustrup: Projektowanie i rozwój języka C++ Paweł Chomicz, Robert Ulijasz: Programowanie w języku C i C++ Tony L. Hansen: C++ zadania i odpowiedzi Adam Majczak: Od C do C++ Buildera w 48 godzin Iwona Adamiec-Wójcik, Pedro Guerreiro: Elementy programowania obiektowego w C++ Programowanie C++
4 Jak szybko przejść od Pascala do C++program p01; { oto twój pierwszy program} begin writeln(' Cześć'); write(' Uczymy się programowania w Pascalu') end. Blok w Pascalu jest ograniczany słowami kluczowymi begin i end. Każda instrukcja, oprócz tej występującej przed słowem kluczowym end kończy się średnikiem. Program główny jest blokiem zakończonym kropką. Komentarze zawierają się w nawiasach klamrowych. # include
5 Co widać na ekranie? Do wyświetlania komunikatów na ekranie w C++ możemy zastosować specjalny obiekt cout wraz z operatorem << (przesyłania do strumienia). Operator << przesyła do strumienia wyjściowego znajdującego się po jego lewej stronie obiekty, które chcemy wyświetlić. Cout oznacza standardowe urządzenie wyjściowe - najczęściej ekran komputera. Dyrektywa # include
6 Zmienne, obiekty i ich deklaracjeZmienna to symbol reprezentujący miejsce w pamięci komputera. Informacja zawarta w tym miejscu pamięci to wartość zmiennej alfa identyfikator zmienna 12345 (integer) wartość typ Deklaracja zmiennej jest instrukcją informującą kompilator o danej zmiennej identyfikator,...,identyfikator : typ; zm1,zm2,zm3:integer; cena,koszt:real; typ identyfikator,...,identyfikator; int zm1,zm2,zm3; float cena,koszt; C++ jest językiem obiektowo-zorientowanym. Zmienne są traktowane jako obiekty; w tym kontekście mówi się, że deklaracja tworzy obiekt. Programowanie C++
7 Słowa kluczowe i identyfikatoryProgram (napisany w dowolnym języku programowania) składa się z pewnych elementów składowych, którymi są: - nazwy zmiennych (zm1,zm2,zm3), - słowa kluczowe (main, void), - operatory (<<, +, -), - znaki punktacji ({, ;, }). Słowa kluczowe w C++: asm auto break case catch char class const continue default delete do double else enum extern float for friend goto if inline int long new operator private protected public register return short signed sizeof static struct switch template this throw try typedef union unsigned virtual void volatile while Identyfikatory: - ciąg znaków alfanumerycznych rozpoczynający się od litery bądź znaku podkreślenia, - małe i duże litery są rozróżniane, - (Numer i numer są różnymi identyfikatorami), - bez spacji, - różne od słów kluczowych. Programowanie C++
8 Instrukcja przypisania, inicjalizacja zmiennychZmienna to miejsce w pamięci. Najczęściej nadanie wartości zmiennej odbywa się przy pomocy instrukcji przypisania. Zmienna może być zainicjalizowana w momencie deklaracji identyfikator : = wyrażenie; cena := 234; litera := 'z'; identyfikator = wyrażenie; cena = 234; litera = 'z'; W C++ znak = jest operatorem przypisania Stała typowa identyfikator :typ=wartość początkowa; i : integer =1; Inicjalizacja w deklaracji typ identyfikator = wyrażenie; int i = 1; int a,b; int sum = a+b; W C++ inicjalizacja jest prawie tym samym co przypisanie. Programowanie C++
9 Przypisanie łańcuchoweW C++ przypisanie jest wyrażeniem z określoną wartością. Wartością wyrażenia x = 22 jest 22 Tak jak każda inna wartość, również i ta może być użyta w innej instrukcji przypisania i wówczas otrzymujemy łączone przypisanie y = ( x = 22 ); = = y = x = 22; # include
10 Typy całkowite i proste operacje arytmetyczneC++ posiada dziewięć następujących typów całkowitych: char short int unsigned short int signed char int unsigned int unsigned char long int unsigned long int Typy te różnią się między sobą zakresem dopuszczalnych wartości. Dopuszczalne granice są stałymi, które znajdują się w pliku nagłówkowym
11 Operatory inkrementacji i dekrementacjiOperator inkrementacji ++ oraz dekrementacji -- zamieniają zmienną w wyrażenie będące instrukcją, które skraca specjalny rodzaj instrukcji przypisania. #include
14 Priorytety i łączność operatorówC++ posiada bardzo bogaty zbiór operatorów. Ponieważ w wyrażeniu może wystąpić więcej operatorów bardzo ważna jest informacja w jakiej kolejności następuje obliczanie wartości wyrażeń. Łączność definiuje w jaki sposób są traktowane operatory o takim samym priorytecie. Programowanie C++
15 Rozmowa z komputerem czyli jak wprowadzać daneW C++ operacje wejściowe są realizowane w podobny sposób jak operacje wyjścia. Dane wprowadzane są ze strumienia wejściowego cin (standardowo klawiatura) przy pomocy operatora wejścia >> (skierowania strumienia). W jednej instrukcji wejściowej może być wczytywanych więcej zmiennych Wczytując zmienne typu char cin ignoruje wszystkie spacje, znaki tabulacji i nowej linii. # include
16 Podejmowanie decyzji - instrukcja ifInstrukcja if pozwala na warunkowe wykonywanie instrukcji if wyrażenie logiczne then instrukcja; if wyrażenie logiczne then instrukcja1 else instrukcja2; if ( warunek ) instrukcja; if ( warunek ) instrukcja1; else instrukcja2; W C++ nie ma typu logicznego; warunek jest wyrażeniem całkowitym. Instrukcja będzie wykonywana jeśli wyrażenie ma wartość niezerową. main() { int n,d; cout<<"Wprowadź dwie liczby całkowite: "; cin>>n>>d; if (n%d = = 0) cout<
17 Wyrażenie logiczne w C++Operatory relacji zwracają wartość 0 dla oznaczenia fałszu oraz 1 dla prawdy. W C++ dowolna wartość może wystąpić w miejscu wyrażenia logicznego. Wartość niezerowa traktowana jest jako prawda, jedynie 0 znaczy fałsz. main() { int n,d; cout<<"Wprowadź dwie liczby całkowite: "; cin>>n>>d; if (n%d ) cout<
18 Instrukcja złożona Instrukcja złożona jest ciągiem instrukcji traktowanym jako pojedyncza instrukcja. Zarówno program główny w Pascalu jak i funkcja main w C++ tworzą instrukcję złożoną zwaną blokiem. var x,y,temp:integer; begin write(‘ Podaj dwie liczby ‘); readln(x,y); if x>y then begin temp:=x; x:=y; y:=temp end; writeln(x,’ ‘,y) end. main() { int x,y; cout<<"Podaj dwie liczby "; cin>>x>>y; if (x>y) { int temp = x; x = y; y = temp; } cout<
19 Operatory logiczne Operatory logiczne służą doformułowania warunków złożonych. W C++ wartość wyrażenia logicznego obliczana jest dotąd, dopóki nie jest pewne jaki będzie rezultat końcowy. main() { int n,d; cout<<"Wprowadź dwie liczby całkowite: "; cin>>n>>d; if (d>0 && n%d ) cout<
20 Instrukcje zagnieżdżoneKażde else łączone jest z ostatnim wolnym if var a,b,c,min3:integer; begin write(‘Podaj trzy liczby ‘); readln(a,b,c); if a<=b then if a<=c then min3:=a else min3:=c else if b<=c then min3:=b else min3:=c; writeln(‘ Minimum wynosi ‘,min3) end. main() { int a,b,c,min3; cout<<"Podaj trzy liczby "; cin>>a>>b>>c; if (a<=b) if (a<=c) min3 = a; else min3 = c; else if (b<=c) min3 = b; cout<<"Minimum wynosi "<
21 Instrukcja wielowariantowaOdpowiednikiem instrukcji case z Pascala jest instrukcja switch case wyrażenie of stała1 : instrukcja1; ... stałan:instrukcjan; else:listainstrukcji end; case ocena of 5: writeln(’bardzo dobry’); 4: writeln(’dobry’); 3: writeln(’dostateczny’); 2: writeln(’niedostateczny’); else writeln(’Błędne dane’); end switch ( wyrażenie) { case stała1 : lista instrukcji1; ... case stałan : lista instrukcjin; default :lista instrukcji } switch (ocena) { case 5: cout<<"bardzo dobry"<
22 warunek ? wyrażenie1 : wyrażenie2Wyrażenie warunkowe W C++ istnieje wyrażenie, które jest skróconą formą instrukcji warunkowej if else warunek ? wyrażenie1 : wyrażenie2 Wartością tego wyrażenia jest wartość wyrażenia1 jeśli warunek jest prawdziwy bądź wartość wyrażenia2 w przypadku przeciwnym. main() // program oblicza minimum z dwóch liczb { int n,m,min; cout<<"Wprowadź dwie liczby całkowite: "; cin>>n>>m; min = n
23 Instrukcje iteracyjnePętle pozwalają na cykliczne wykonywanie instrukcji. while wyrażenie logiczne do instrukcja; while ( warunek ) instrukcja; Obliczana jest wartość warunku; instrukcja jest wykonywana tak długo dopóki wartość warunku jest różna od zera. repeat ciąg instrukcji until warunek; do instrukcja while ( warunek ); Najpierw wykonywana jest instrukcja a następnie sprawdzany warunek, którego wartość równa zero kończy wykonywanie instrukcji. for identyfikator := wyrażenie1 to wyrażenie2 do instrukcja for ( inicjalizacja ; warunek kontynuacji ; wyrażenie) instrukcja ; Inicjalizowana jest zmienna sterująca pętli, następnie jeśli warunek jest spełniony to instrukcja jest wykonywana. Wyrażenie określa zmianę zmiennej. Programowanie C++
24 Pętle while i do...while Obie pętle wykonują instrukcję będącą ciałem pętli tak długo dopóki warunek jest prawdziwy czyli dopóki jego wartość jest różna od zera. main( ) { int age; cout<<”Ile masz lat : "; cin>>age; while (age<=0) {cout<<"Wiek musi być >0\n”; } Pętla while wymaga by warunek był określony, co czasami wiąże się z koniecznością wykonania instrukcji przed rozpoczęciem pętli. main( ) {int age; do {cout<<”Ile masz lat : "; cin>>age; } while (age<=0); } Pętla do...while jest wykonywana przynajmniej raz a warunek sprawdzany jest po wykonanej instrukcji. Programowanie C++
25 Pętla for Pętla for najczęściej używana jest do wykonywania określonej liczby powtórzeń. W C++ instrukcja for jest jedynie bardziej zwartym zapisem pętli while. Wszystkie trzy części występujące w nawiasie po słowie kluczowym for są opcjonalne. Może wystąpić np. tylko warunek: Instrukcja inicjalizacji może zawierać deklarację zmiennej. Zmienna ta nie jest lokalna dla pętli: for (int i=1; i<=20; i++) cout<< "Cześć”<
26 Jeszcze o pętli for W Pascalu zmienna sterująca pętli for musiała być typu porządkowego. W C++ ta zmienna nie musi wystąpić, a jeśli się pojawia to może być dowolnego typu. Pętla for może być również użyta dla więcej niż jednej zmiennej sterującej #include
28 Standardowe funkcje matematyczneFunkcje matematyczne zdefiniowane są w pliku nagłówkowym
29 Funkcje zwracające wartośćStandardowe funkcje biblioteczne nie zawierają wszystkich funkcji potrzebnych programiście. Funkcje definiowane muszą zawierać nagłówek funkcji: typ identyfikator( lista parametrów formalnych ) oraz ciało funkcji: { ciąg instrukcji; return wyrażenie; } Lista parametrów formalnych jest opcjonalna. Muszą jednak pozostać nawiasy. W C++ deklaracja funkcji może być umieszczona przed funkcją main() a jej definicja może być umieszczona po funkcji. int cube(int x) { return x*x*x; } int max(int x, int y) { if (x
30 Oddzielna kompilacja Bardzo często funkcje są kompilowane oddzielnie i umieszczane w oddzielnych plikach. Sprzyja to „ukrywaniu informacji” użytecznemu w dużych projektach. test_max.cpp int max(int,int); W Borland C++ aby dwa oddzielne pliki zlinkować main() należy użyć projektu. { int m,n; do { cin>>m>>n; cout<
31 Funkcje typu void Funkcje nie zwracające żadnej wartości, będące odpowiednikiem procedur nazywane są często funkcjami typu void. Nagłówek takiej funkcji jest postaci: void identyfikator (lista parametrów) void drukuj_dzien( int nr_d) { switch (nr_d){ case 0: cout<<"Niedziela"<
32 Parametry przekazywane przez wartośćParametry przekazywane przez wartość nie ulegają zmianie, gdyż funkcja działa na kopii parametru aktualnego umieszczonej na stosie. #include
33 Przekazywanie adresów zmiennychAby funkcja mogła dokonać zmiany parametru musi mieć dostęp do samej zmiennej (np. poprzez jej adres). void swap(float *x, float *y) { float temp = *x; *x = *y; *y = temp; * wskaźnik - zmienna zawierająca } a = 500 b = adres void main( ) a = 400 b = 500 & operator adresu - pobiera adres { zmiennej float a = 500, b = 400; cout<<"a = "< swap(&a, &b); } Programowanie C++
34 typ& alias = identyfikatorReferencja Referencja jest aliasem (drugą nazwą) zmiennej. Deklaracja referencji wymaga podania zmiennej, dla której tworzona jest referencja typ& alias = identyfikator void main() { int a = 500; int& b = a; cout<<" zmienna = "< b+=500; } Referencja NIE JEST zmienną : nie można zmieniać jej wartości, nie nożna pobrać jej adresu, nie można przypisać jej wskaźnika zmienna = 500 alias = 500 zmienna = 1000 alias = 1000 Programowanie C++
35 Parametry przekazywane przez referencjęParametry przekazywane przez referencję ulegają zmianie gdyż do funkcji przekazywany jest adres zmiennej void swap(float& x, float& y) { float temp = x; x = y; y = temp; } a = 500 b = void main() a = 400 b = 500 { float a = 500, b = 400; cout<<"a = "< swap(a, b); } Parametr aktualny odpowiadający parametrowi formalnemu przekazywanemu przez referencję musi być zmienną. Programowanie C++
36 Porównanie parametrów Porównanie parametrów Podsumowanie różnic pomiędzy przekazywaniem parametrów przez wartość i przez referencję: Przekazywanie przez wartość Przekazywanie przez referencję int x; int& x; Parametr formalny jest zmienną lokalną; Parametr formalny jest lokalną referencją; Jest kopią parametru aktualnego; Jest synonimem parametru aktualnego; Nie można zmienić parametru Można zmienić parametr aktualny; aktualnego; Parametr aktualny może być stałą, Parametr aktualny musi być zmienną. zmienną bądź wyrażeniem. Jest to odpowiednik przekazywania Jest to odpowiednik przekazywania przez przez wartość w Pascalu. zmienną w Pascalu. Programowanie C++
37 Parametry przekazywane przez stałą referencję Parametry przekazywane przez stałą referencję Duże obiekty są przekazywane przez referencję aby nie tworzyć ich kopii. Jeśli nie chcemy, by uległy zmianie można je przekazywać przez stałą referencję. void f(int x, int& y, const int& z) { x+=z; y+=z; cout<<" x = "<
38 Funkcje typu inline Wywołanie funkcji związane jest z dodatkowym czasem i pamięcią. W niektórych przypadkach korzystniejsze jest zdefiniowanie funkcji jako inline. inline int cube( int n) { return n*n*n; } main ( ) main ( ) { { cout<
39 Zakres widoczności zmiennych Zakres widoczności zmiennych Zmienna lokalna - zmienna deklarowana wewnątrz bloku; widoczna jest od miejsca deklaracji do końca najbardziej wewnętrznego bloku; Zmienna globalna - zmienna dostępna w całym programie; deklarowana na zewnątrz wszystkich funkcji; Operator zakresu - :: pozwala na dostęp do zmiennej globalnej z bloku, w którym jest zadeklarowana zmienna lokalna o takiej samej nazwie. void f( ); int x = 9; void main( ) { int x = 22; cout<<" x w main = "<
40 Przeciążenie (overloading) Przeciążenie (overloading) C++ pozwala na użycie tej samej nazwy dla różnych funkcji. Aby funkcje były rozróżniane lista parametrów musi zawierać różną liczbę parametrów albo musi wystąpić różnica typu przynajmniej jednego parametru int max (int, int); int max (int, int, int); float max(float, float); void main ( ) { cout<
41 Parametry domyślne Dzięki parametrom domyślnym liczba parametrów w wywołaniu funkcji może się zmieniać. double p( double, double, double=0, double=0, double=0); main( ) { double x = ; cout<<"p(x,7) = "< cout<<"p(x,7,6) = "< cout<<"p(x,7,6,5) = "< cout<<"p(x,7,6,5,4) = "< } double p( double x, double a0, double a1, double a2, double a3) return a0+(a1+(a2+a3*x)*x)*x; p(x,7) = 7 p(x,7,6) = p(x,7,6,5) = p(x,7,5,4) = Parametry z wartościami domyślnymi muszą wystąpić na końcu listy parametrów. Jeśli w wywołaniu pomija się któryś z parametrów to trzeba pominąć również wszystkie następne. Programowanie C++ 42 Czas życia zmiennych Czas życia obiektu trwa od momentu jego deklaracji do momentu kiedy przestaje istnieć - obiekt może być niewidoczny ale istnieć. Obiekty automatyczne - obiekty, które wraz z zakończeniem bloku, w którym zostały powołane do życia przestają istnieć. Obiekty automatyczne w chwili deklaracji nie są zerowane. Obiekty lokalne statyczne - obiekty deklarowane lokalnie, static typ identyfikator; zakres widoczności tych obiektów odnosi się do bloku ale ich czas życia jest taki jak obiektów void f( ) globalnych. { static int licznik; licznik++ } Programowanie C++ 43 Tablice Tablica - strukturalny typ danych będący ciągiem obiektów tego samego typu. Składniki tablicy zwane elementami są dostępne poprzez indeksy. identyfikator : array [zakres] of typ typ identyfikator[stała] a: array [1..3] of integer; int a [3]; a[1], a[2], a[3] a[0], a[1], a[2] - indeksy tablicy mogą być - stała określa liczbę elementów z dowolnego zakresu. Numeracja elementów rozpoczyna się zawsze od zera. Element o indeksie równym stałej nie istnieje. Programowanie C++ 44 Inicjalizacja tablic Zmienna tablicowa tak jak każda inna zmienna może zostać zainicjalizowana w momencie deklaracji. int a[3] = {1,2,3}; - inicjalizacja w deklaracji to jedyne miejsce, gdzie kompilator sprawdza zakres tablicy: int a[3]={1,2,3,4} ŹLE int a[3] = {1,2} - jeżeli liczba elementów jest większa niż liczba wartości, to zadane wartości zostaną przyporządkowane pierwszym elementom a pozostałe będą inicjalizowane zerem; int a[ ] = {1,2,3,4} -jeśli nie podajemy rozmiaru tablicy, to kompilator liczy wartości i rezerwuje pamięć na tablicę o takim rozmiarze; Programowanie C++ 45 Przekazywanie tablic do funkcji Przekazywanie tablic do funkcji const int size=100; void getArray(double [ ], int&); void printArray(const double[ ], const int); int main() { double a[size]; int n; getArray(a,n); cout<<"Tablica ma "< 46 Typ wyliczeniowy Typ wyliczeniowy jest typem całkowitym i jest jednym z najprostszych typów definiowanych przez użytkownika: type identyfikator = ( lista wartości) enum identyfikator{ lista wartości } Lista wartości jest listą identyfikatorów definiujących stałe całkowite rozpoczynając od zera. main () { enum Day = {sun, mon, tue, wed, thu, fri, sat} float temp[sat+1] = {23.0, 22.4, 21.0, 18.5, 19.0, 20.2, 19.0} for (Day day=sun; day<=sat; day++) cout<<" Temp max w dniu "< 47 Definiowanie typów Typ wyliczeniowy w C++ ma kilka cech, których nie miał odpowiadający mu typ z Pascala: Nie zawsze jest to typ porządkowy. enum Base {bin = 2, oct = 8, dec = 10, hex = 16} -można nadawać wartości poszczególnym identyfikatorom; enum Answer {no = 0, false = 0, yes = 1, ok = 1} - może wystąpić kilka identyfikatorów z taką samą wartością; C++ umożliwia nadawanie nowych nazw istniejącym typom: typedef typ alias; typedef long Integer; Integer n; typedef double Real; Real x; typedef float tablica[ ]; tablica a; Programowanie C++ 48 Tablice wielowymiarowe Tablice wielowymiarowe Elementy tablicy mogą być dowolnego typu nie wyłączając typu tablicowego. Otrzymujemy wówczas tablicę tablic zwaną tablicą wielowymiarową. void print(const int a[][5]); - tablica wielowymiarowa przekazywana do main() funkcji musi zawierać zakresy wszystkich { pozostałych wymiarów oprócz pierwszego; int a[2][5]={ 1, 2, 3, 4, 5, 6, 7, 8, 9,10} - wartości tablicom wielowymiarowym są print(a); przypisywane wierszami, co można zaznaczyć } przy pomocy nawiasów klamrowych; void print(const int a[][5]) { for (int i=0;i<2;i++){ for(int j=0; j<5; j++) cout<<" "< cout< 49 Wskaźniki Wskaźniki to zmienne, których wartościami są adresy innych zmiennych. identyfikator : ^typ typ* identyfikator Deklaracja zmiennej wskaźnikowej musi zawierać informację o typie zmiennych, na które wskaźnik może pokazywać. main() { int n=33; int* p=&n; - inicjalizacja zmiennej wskaźnikowej int& r = *p; - deklaracja i inicjalizacja referencji cout<<" n = "< 51 Zwracanie referencji przez funkcję Zwracanie referencji przez funkcję Typ zwracany przez funkcję może być referencją pod warunkiem, że wartość zwracana jest l-wartością, która nie jest lokalna dla funkcji. int& max(int& m, int& n) { return (m>n ? m:n) } main() int m = 44, n = 22; cout< 52 Tablice i wskaźniki Wskaźniki mogą być wykorzystywane do działań na tablicach. Wskaźniki mogą być inkrementowane main( ) i dekrementowane. Oznacza to { przesunięcie wskaźnika o wielkość const int size = 3; odpowiadającą obiektowi, na który int a[size]={11,22,33}; wskazuje. cout<<"a = "< < 53 54 Operator new Wskaźnik można zainicjalizować poprzez podanie adresu zmiennej bądź użycie operatora new, który rezerwuje miejsce w pamięci, na które wskaźnik pokazuje. float* p; // p jest wskaźnikiem do float *p = 3.14; // ERROR: nie została przydzielona pamięć, na którą ma wskazywać p float x=3.14; // zainicjalizowanie zmiennej x; alokacja pamięci pod nazwą x float*p = &x; // wskaźnik zawiera adres zmiennej x *p = 3.14; // O.K.: *p wskazuje na określone miejsce w pamięci float* q; q = new float; //przydzielenie pamięci dla float; alokacja pamięci bez nazwy *q = 3.14; //O.K.: pamięć została przydzielona float* p = new float; float* q = new float(3.14); Operator new zwraca adres określonej liczby bajtów wolnej pamięci. Programowanie C++ 55 Operator delete Operator delete odwraca działanie operatora new zwracając określoną liczbę bajtów pamięci jako wolną do zagospodarowania. float* q = new float; delete q; // zwolnienie pamięci przydzielonej dla wskaźnika q *q = 3.14; //ERROR: q nie pokazuje na żaden obiekt. Za pomocą operatora delete kasuje się tylko obiekty stworzone operatorem new poza wskaźnikami do stałych. float x = 3.14; float* p = &x; delete p; //RYZYKOWNE: p nie było tworzone przez new; const int* p = new int; delete p; //ERROR: nie można zlikwidować wskaźnika do stałej Programowanie C++ 56 Tablice dynamiczne Obiekty dynamiczne - obiekty tworzone w trakcie wykonywania programu przez użycie operatorów new i delete. void get(double*& a, int& n) { // funkcja tworzy tablicę dynamiczną cout<<"Podaj liczbę elementów: "; new typ [wyrażenie] cin>>n; delete [ ] wskaźnik a = new double [n]; for (i=0; i 57 Użycie const ze wskaźnikamiWskaźnik do stałej to coś innego niż stały wskaźnik. int* p; // wskaźnik do int ++(*p); ++p; int* const cp; // stały wskaźnik do int ++(*cp); ++cp; const int* pc; // wskaźnik do stałej int ++(*pc); ++pc; const int* const cpc; //stały wskaźnik do stałej int ++(*cpc); ++cpc; Programowanie C++ 58 Tablice wskaźników i wskaźniki do wskaźnikówElementami tablic mogą być wskaźniki int* a[4]; // pośrednie sortowanie bąbelkowe a[2] = new int(4); // tablicy wskaźników void sort(float* p[ ], int n) Wskaźnik może pokazywać na inny wskaźnik { float* temp; char c = ’t’; for(i=1; i 59 Wskaźniki do funkcji Nazwa funkcji podobnie jak nazwa tablicy jest stałym wskaźnikiem. int f ( int ); // deklaracja funkcji int (*pf) ( int ); // deklaracja wskaźnika do funkcji pf = &f; // inicjalizacja wskaźnika adresem funkcji int sum(int (*)(int), int); int square(int); int cube (int); main() { cout<< sum (square,4)< 60 Łańcuchy String jest kolekcją znaków zakończonych znakiem ’\0’ (NULL) traktowanych jako pojedynczy obiekt. W C++ string jest tablicą znaków o pewnych wyjątkowych cechach: - Dodatkowy element jest dodawany na końcu tablicy i jego wartość wynosi NULL; Liczba elementów w tablicy jest o jeden większa niż długość łańcucha - Łańcuch może być inicjalizowany stałą łańcuchową char str[ ]= "Hello"; - Łańcuch może być wysłany do strumienia wyjściowego jako pojedynczy element cout< 61 Inicjalizacja łańcuchówJeśli wypełniamy tablicę znaków element po elemencie należy pamiętać o umieszczeniu znaku NULL na końcu. Kompilator C++ automatycznie dołącza znak NULL na końcu stałej tekstowej. main() { char alfabet[27]; //26 liter + NULL char litera; int indeks; for(litera='A', indeks=0; litera<='Z';litera++) alfabet[indeks]=litera; alfabet[indeks]=NULL; cout<<"Litery alfabetu: "< 62 Łańcuch jako wskaźnik i tablice łańcuchówNazwa tablicy jest jej adresem - string można traktować jako wskaźnik do pierwszego elementu łańcucha. char* p; Jeśli p jest wskaźnikiem do dowolnego typu to cout< w przypadku gdy p jest wskaźnikiem do char cout< main() { char* name[] = {" George Washington", " John Adams", "Thomas Jefferson" } for(int i=0; i<3; i++) cout<<"\t"< } 0. [ George Washington ] 1. [ John Adams ] 2. [ Thomas Jefferson ] Programowanie C++ 63 Funkcje biblioteczne 64 Użycie funkcji bibliotecznych#include =q, p>q; p==q; p!=q
p - q; p + n; Operator logicznego przeczenia p - n; !p wynikiem jest 1 jeśli wskaźnik p jest NULL, w przeciwnym przypadku wynik jest równy 0. Programowanie C++