Język C++. Pierwsze starcie
 978-83-246-4507-7 [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Redakcja: Michał Mrowiec Redakcja techniczna, opracowanie tekstu i skład: Zbigniew Koza Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 032 231 22 19, 032 230 98 63 e-mail: [email protected] WWW: http://helion.pl (księgarnia internetowa, katalog książek) Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie?jcppps_ebook Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/jcppps.zip ISBN: 978-83-246-4507-7 Copyright © Helion 2008 Printed in Poland.

• Poleć książkę na Facebook.com • Kup w wersji papierowej • Oceń książkę

• Księgarnia internetowa • Lubię to! » Nasza społeczność

Wszystkim Kózkom – dużym i małym

Spis treści Wstęp

9

1. Pierwszy program w C++ 1.1. Dla kogo jest ta książka? . . . . . . . . . . . . . . . . . . . . . . 1.2. Rys historyczny . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3. Zanim napiszesz swój pierwszy program . . . . . . . . . . . . . 1.4. Pierwszy program . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5. Obiekt std::cout i literały . . . . . . . . . . . . . . . . . . . . 1.6. Definiowanie obiektów . . . . . . . . . . . . . . . . . . . . . . . 1.7. Identyfikatory, słowa kluczowe i dyrektywy . . . . . . . . . . . . 1.8. Zapis programu . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.9. Cztery działania matematyczne i typ double . . . . . . . . . . 1.10. Jeszcze więcej matematyki . . . . . . . . . . . . . . . . . . . . . 1.11. Upraszczanie zapisu obiektów i funkcji biblioteki standardowej 1.12. Źródła informacji . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.13. Q & A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.14. Pytania przeglądowe . . . . . . . . . . . . . . . . . . . . . . . . 1.15. Problemy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

13 13 13 16 18 21 22 24 24 25 26 28 28 29 30 30

2. Wyrażenia i instrukcje 2.1. Instrukcje sterujące . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Pętle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3. Typy wbudowane . . . . . . . . . . . . . . . . . . . . . . . . . 2.4. Wyrażenia arytmetyczne, promocje i konwersje standardowe 2.5. Tworzenie obiektów stałych . . . . . . . . . . . . . . . . . . . 2.6. Popularne typy standardowe . . . . . . . . . . . . . . . . . . . 2.7. Obiekty lokalne i globalne. Zasięg. Przesłanianie . . . . . . . 2.8. Operatory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9. Wyrażenia i instrukcje . . . . . . . . . . . . . . . . . . . . . . 2.10. Q & A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.11. Pytania przeglądowe . . . . . . . . . . . . . . . . . . . . . . . 2.12. Problemy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

31 31 33 36 41 43 44 50 51 57 58 58 58

3. Funkcje 3.1. Referencje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2. Funkcje swobodne . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61 61 62

. . . . . . . . . . . .

6

Spis treści

3.3. 3.4. 3.5. 3.6. 3.7. 3.8. 3.9. 3.10. 3.11. 3.12. 3.13. 3.14. 3.15. 3.16. 3.17. 3.18. 3.19.

Po co są funkcje? . . . . . . . . . . . . Funkcje składowe – wprowadzenie . . Argumenty funkcji . . . . . . . . . . . . Funkcje zwracające referencję . . . . . Operatory jako funkcje swobodne . . . Stos funkcji . . . . . . . . . . . . . . . . Funkcje otwarte (inline) . . . . . . . Funkcje jako argumenty innych funkcji Rekurencja . . . . . . . . . . . . . . . . Argumenty domyślne . . . . . . . . . . Lokalne obiekty statyczne . . . . . . . Funkcja main . . . . . . . . . . . . . . Polimorfizm nazw funkcji . . . . . . . . Deklaracja a definicja funkcji . . . . . . Q &A . . . . . . . . . . . . . . . . . . . Pytania przeglądowe . . . . . . . . . . Problemy . . . . . . . . . . . . . . . . .

4. Tablice i wskaźniki 4.1. Wskaźniki . . . . . . 4.2. Tablice . . . . . . . . 4.3. Pamięć wolna (sterta) 4.4. Q & A . . . . . . . . . 4.5. Pytania przeglądowe 4.6. Problemy . . . . . . . 5. Klasy 5.1. 5.2. 5.3. 5.4. 5.5. 5.6. 5.7. 5.8. 5.9. 5.10. 5.11. 5.12.

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

64 66 66 69 70 73 75 77 77 78 79 81 82 82 83 83 83

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

85 85 89 96 98 98 99

i obiekty Struktury . . . . . . . . . . . . . . . . Co to są klasy? . . . . . . . . . . . . Definiowanie klas . . . . . . . . . . . Funkcje składowe (metody) . . . . . . Udostępnianie składowych . . . . . . Interfejs i implementacja . . . . . . . Kontrakty, niezmienniki i asercje . . . Hermetyzacja danych . . . . . . . . . Różnice między klasami i strukturami Dygresja: składowe statyczne . . . . Pytania przeglądowe . . . . . . . . . Problemy . . . . . . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

101 101 104 104 109 115 117 120 122 122 123 124 125

. . . . . . klas . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

127 127 134 137 139 139 140

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

6. Dynamiczne struktury danych 6.1. Stos na bazie tablicy dynamicznej . . . . . . . . . . . 6.2. Stos na bazie listy pojedynczo wiązanej . . . . . . . 6.3. Dygresja: przestrzenie nazw i zagnieżdżanie definicji 6.4. Q & A . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5. Pytania przeglądowe . . . . . . . . . . . . . . . . . . 6.6. Problemy . . . . . . . . . . . . . . . . . . . . . . . . .

Spis treści

7. Dziedziczenie i polimorfizm 7.1. Dziedziczenie . . . . . 7.2. Polimorfizm . . . . . . . 7.3. Jak to się robi w Qt? . 7.4. Q & A . . . . . . . . . . 7.5. Pytania przeglądowe . 7.6. Problemy . . . . . . . .

7

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

141 141 151 157 161 161 162

8. Strumienie 8.1. Strumienie buforowane i niebuforowane . . 8.2. Klawiatura, konsola, plik, strumień napisowy 8.3. Stan strumienia . . . . . . . . . . . . . . . . 8.4. Manipulatory i formatowanie strumienia . . 8.5. Strumienie wyjścia . . . . . . . . . . . . . . 8.6. Strumienie wejścia . . . . . . . . . . . . . . 8.7. Przykład . . . . . . . . . . . . . . . . . . . . 8.8. Pytania przeglądowe . . . . . . . . . . . . . 8.9. Problemy . . . . . . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

163 163 164 166 167 169 169 171 173 174

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

9. Biblioteki 9.1. Podział programu na pliki . . . . . . . . . . . . 9.2. Używanie gotowych bibliotek . . . . . . . . . . . 9.3. Kompilacja i instalacja programów lub bibliotek z plików źródłowych . . . . . . . . . . . . . . . . 9.4. Pytania przeglądowe . . . . . . . . . . . . . . . 9.5. Problemy . . . . . . . . . . . . . . . . . . . . . . 10. Preprocesor i szablony 10.1. Preprocesor . . . . . 10.2. Szablony . . . . . . . 10.3. Pytania przeglądowe 10.4. Problemy . . . . . . .

175 . . . . . . . . . . . . 175 . . . . . . . . . . . . 184 . . . . . . . . . . . . 188 . . . . . . . . . . . . 190 . . . . . . . . . . . . 190

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

191 191 197 205 206

11. Wprowadzenie do STL 11.1. Co to jest STL? . . . . . 11.2. Pojemniki . . . . . . . . . 11.3. Iteratory . . . . . . . . . . 11.4. Algorytmy . . . . . . . . . 11.5. Wektory (std::vector) 11.6. Liczby zespolone . . . . 11.7. Napisy (std::string) . 11.8. Q & A . . . . . . . . . . . 11.9. Pytania przeglądowe . . 11.10. Problemy . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

207 207 208 208 211 218 222 223 224 225 225

. . . .

12. Pojemniki i algorytmy 227 12.1. Przegląd pojemników STL . . . . . . . . . . . . . . . . . . . . . . . . 227

8

Spis treści

12.2. 12.3. 12.4. 12.5. 12.6. 12.7.

Przegląd algorytmów swobodnych Kontrola poprawności użycia STL Składniki dodatkowe . . . . . . . Q &A . . . . . . . . . . . . . . . . Pytania przeglądowe . . . . . . . Problemy . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

13. Obsługa błędów 13.1. Rodzaje błędów . . . . . . . . . . . . . . . 13.2. Analiza błędów składniowych: koncepty . 13.3. Wykrywanie błędów logicznych: debuger . 13.4. Obsługa błędów czasu wykonania: wyjątki 13.5. Q & A . . . . . . . . . . . . . . . . . . . . . 13.6. Pytania przeglądowe . . . . . . . . . . . . 13.7. Problemy . . . . . . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

239 246 248 248 248 249

. . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

251 251 252 254 257 267 267 268

. . . . . .

. . . . . .

. . . . . .

14. Co dalej? 271 14.1. Problemy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 A. Dodatki A.1. Wybrane opcje kompilatora g++ . . A.2. Dodatkowe elementy języka . . . . A.3. Zgodność języka C++ z językiem C A.4. Przyszłość języka C++ . . . . . . . A.5. Źródła informacji w internecie . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

273 273 275 276 277 278

Wstęp Niniejsza książka pomyślana jest jako kurs języka C++ na poziomie podstawowym i średniozaawansowanym. Oparta jest na moich doświadczeniach jako wykładowcy tego języka dla sekcji komputerowej Wydziału Fizyki i Astronomii Uniwersytetu Wrocławskiego, a adresowana jest do wszystkich osób, które chcą nauczyć się współczesnego języka C++ od podstaw i dla których prawdopodobnie już wkrótce będzie on podstawowym narzędziem w pracy zawodowej. Co wyróżnia tę książkę spośród kilkudziesięciu innych dostępnych aktualnie na rynku? Po pierwsze, książka ma strukturę podręcznika. Materiał wprowadzany jest stopniowo w kilkunastu rozdziałach o starannie przemyślanej kolejności i rosnącym stopniu trudności. Każdy z nich poświęcony jest jednemu tematowi i kończy się pytaniami kontrolnymi oraz zadaniami do samodzielnego rozwiązania. Po drugie, C++. Pierwsze starcie nie zawiera pełnego opisu C++. Język ten zawiera bowiem liczne konstrukcje przeznaczone do bardzo specjalistycznych zastosowań, w związku z czym nawet zawodowi programiści z reguły nie znają wszystkich jego meandrów. Dlatego świadomie zawęziłem zakres omawianych tematów do tych najbardziej potrzebnych adeptom C++. Dzięki temu powstał stosunkowo niewielki rozmiarem, tani podręcznik, zawierający jednak wszystkie informacje niezbędne do zrozumienia istoty C++. Po jego przestudiowaniu Czytelnik powinien być w stanie uczestniczyć w typowym projekcie programistycznym i samodzielnie rozwijać swoje umiejętności w zakresie programowania, np. studiując bardziej zaawansowane podręczniki, wymieniając doświadczenia z innymi programistami bądź używając specjalistycznych bibliotek napisanych w języku C++ lub C. Po trzecie, książka opisuje współczesny język C++, Anno Domini 2008. Zarówno standard, jak i praktyka posługiwania się tym bodaj najpopularniejszym obecnie językiem programowania podlegają ciągłej ewolucji. W podręczniku opisuję obowiązujący obecnie standard z 1998 roku (tzw. C++98), kładąc duży nacisk na elementy, które dopiero w 1998 roku zostały oficjalnie włączone do języka, a w szczególności na standardową bibliotekę szablonów (STL). Uwzględniając stopniową ewolucję C++, w ostatnich rozdziałach książki podaję także informacje o jego kilku popularnych rozszerzeniach, które prawdopodobnie zostaną włączone do C++ w planowanej na 2009 rok aktualizacji standardu (znanej obecnie jako C++0x). Po czwarte, książka nie jest suchym raportem języka. Osoby, do których adresowany jest ten podręcznik, nie są profesjonalistami i potrzebują dość szczegółowych informacji o otoczeniu, w jakim wykorzystywany jest C++ oraz możliwie realistycznych przykładów jego zastosowań. Dlatego książka zawiera wiele praktycznych informacji o takich na-

10

Wstęp

rzędziach, jak kompilator, debuger i zintegrowane środowisko programistyczne, a także przykłady użycia standardowych i – co szczególnie ważne – typowych niestandardowych bibliotek, zarówno w systemach BSD/Linux, jak i WindowsTM . Jako że programy narzędziowe nie są objęte standardem, musiałem dokonać wyboru konkretnych rozwiązań. W zakresie kompilatora wybór był łatwy: GNU gcc/g++. Jest to dojrzały, systematycznie udoskonalany, darmowy kompilator o ogólnie dostępnym kodzie źródłowym, który można uruchomić na praktycznie każdym współczesnym komputerze. Aby w pełni wykorzystać jego walory, użytkownicy systemu WindowsTM powinni dodatkowo zainstalować pakiet programów narzędziowych GNU, np. MSYS (http://www.mingw.org/). Mając świadomość, że zdecydowana większość potencjalnych czytelników tej książki posługuje się systemem operacyjnym z rodziny WindowsTM , wszystkie przedstawione w tym podręczniku programy pisałem i testowałem właśnie w tym systemie. Z wyjątkiem programu 9.5, który wykorzystuje działającą wyłącznie w systemach WindowsTM bibliotekę DirectX, wszystkie omawiane tu przykłady zostały też przetestowane w systemie Linux, przy czym niektóre z nich (a szczególnie te z ostatniego rozdziału książki) dużo łatwiej jest studiować właśnie w systemach uniksowych. Takie zawieszenie omawianych przykładów pomiędzy dwoma popularnymi systemami operacyjnymi powinno uświadomić Czytelnikowi, że C++ daje pełną swobodę w wyborze zarówno kompilatora, jak i systemu operacyjnego i że wybór rozwiązań niekomercyjnych nie tylko nie oznacza rezygnacji z możliwości tworzenia ciekawych programów, ale daje też wolność tworzenia aplikacji, które można uruchomić praktycznie na każdym współczesnym komputerze, a także gwarancję, że wolność ta nie jest i nie będzie przez nikogo ograniczona. Pisząc tę książkę, starałem się uniknąć częstego błędu, jakim jest jednostronna prezentacja C++ czy to jako „lepszej wersji” języka C, czy też jako języka wyłącznie obiektowego. Nie dość, że oba te podejścia zacierają prawdziwą naturę języka C++, to w dodatku są niepedagogiczne – pierwsze prowadzi do sytuacji, w której udogodnienia języka C++ w stosunku do języka C traktowane są przez studentów jako niepotrzebne i niezrozumiałe utrudnienia, drugie jest zbyt abstrakcyjne dla osób dopiero rozpoczynających przygodę z programowaniem. Język C++ daje swobodę w wyborze stylu programowania i zawiera harmonijnie uzupełniające się mechanizmy umożliwiające zarówno stosowanie abstrakcji danych, jak i programowanie w stylu proceduralnym („lepsze C”), obiektowym bądź generycznym. Dlatego już od pierwszych rozdziałów, z konieczności poświęconych głównie proceduralnym aspektom języka, wprowadzam klika użytecznych konstrukcji generyczno-obiektowych (strumienie, napisy, wektory) i konsekwentnie używam ich w całym podręczniku. Jednocześnie ograniczam do absolutnego minimum użycie wskaźników i tablic, czyli niskopoziomowych typów danych, których bezbłędne użycie wymaga dużego doświadczenia. Język C++ jest trudny zarówno do nauczania, jak i uczenia się. Nie powstał bowiem (jak np. Pascal) w wyniku teoretycznych rozważań nad metodologią programowania; przeciwnie, C++ został zaprojektowany przez praktyków jako narzędzie mające pomóc w rozwiązaniu problemów praktycznych. Problemów, dodajmy, które objawiają się dopiero w dużych projektach i mają związek z wydajnością i kosztami pracy programistów. Tu właśnie tkwi źródło trudności w dydaktyce C++: niemal wszystkie charakterystyczne elementy tego języka, które odróżniają go od takich języków, jak C czy Pascal, znajdują zastosowanie (i uzasadnienie!) dopiero w dużych projektach. Tymczasem kurs poświęcony podstawom języka musi ograniczać się do omawiania nienaturalnie krótkich

Wstęp

11

programów, w których wiele sztandarowych udogodnień języka C++ traci jakiekolwiek znaczenie praktyczne. O ograniczeniu tym powinni pamiętać szczególnie ci Czytelnicy, którzy nie mają żadnego doświadczenia w pisaniu poważniejszych aplikacji. Jednym z głównych założeń projektowych języka C++ jest maksymalne ułatwienie tworzenia (a w konsekwencji także używania) bibliotek. W gruncie rzeczy każdy program napisany w języku C++ korzysta z jakiejś biblioteki. Biblioteka standardowa C++ z założenia zawiera tylko te klasy i funkcje, które są dostatecznie uniwersalne, by mogły być zaakceptowane przez każdego producenta oprogramowania. Stąd też nie ma w niej funkcji służących do obsługi graficznego interfejsu użytkownika, baz danych czy połączeń sieciowych. Nie ma ich w standardzie, ale tego typu usługi są powszechnie dostępne w licznych bibliotekach, zarówno komercyjnych, jak i niekomercyjnych. Bibliotekach, dodajmy, które mogą być napisane nie tylko w C++, ale także w C lub innych językach, i które mogą posługiwać się różnymi paradygmatami programowania. Dlatego w mojej książce przedstawiam wiele praktycznych przykładów użycia różnorodnych bibliotek, począwszy od generyczno-obiektowej biblioteki standardowej, poprzez zamknięte, komercyjne biblioteki charakterystyczne dla systemu WindowsTM , biblioteki napisane w języku ANSI C, na bibliotekach obiektowych z projektów GNU i Qt kończąc. Opanowanie typowych sposobów używania bibliotek jest najważniejszym zadaniem stojącym przed każdym adeptem C++, a biegłość w tej dziedzinie – podstawowym probierzem praktycznej znajomości języka. Zadziwiające, ale ten kluczowy aspekt programowania w C++ w większości podręczników jest traktowany bardzo powierzchownie, co zapewne wynika z faktu, że nie jest on objęty żadnym standardem. Nacisk na praktyczną naukę posługiwania się bibliotekami jest prawdopodobnie najważniejszym wyróżnikiem niniejszego podręcznika. Jak już wspomniałem, każdy rozdział kończy się pytaniami kontrolnymi i zadaniami. Pytania służą do sprawdzenia stopnia zrozumienia materiału i dotyczą wyłącznie treści omawianych w danym rozdziale. Z kolei zadania służą praktycznemu utrwaleniu oraz rozszerzeniu zdobytej wiedzy. Dlatego rozwiązanie wielu z nich wymagać będzie pomysłowości oraz poszukiwania dodatkowych informacji poza podręcznikiem. Odzwierciedla to fakt, że programowanie jest aktem twórczym i wymaga od programistów nie tylko opanowania rzemiosła, ale i kreatywności oraz samodzielności. Podręcznik składa się z trzynastu rozdziałów. Stopień zaawansowania kilku początkowych dostosowany jest do potrzeb (i poziomu) osób piszących nie tyle nawet programy, ile krótkie „wprawki”. Pierwszy rozdział zawiera krótki opis języka, kilka przykładowych programów oraz informacje niezbędne do ich kompilacji. Kolejne trzy rozdziały zawierają zwięzły opis nieobiektowych cech języka, a więc m.in. konstrukcji wyrażeń i instrukcji, definiowania zmiennych i tablic oraz posługiwania się funkcjami swobodnymi. Cztery pierwsze rozdziały wprowadzają więc Czytelnika w świat programowania proceduralnego w C++ lub, innymi słowy, w świat C++ traktowanego jako „ulepszona” wersja języka C. Kolejne cztery rozdziały poświęcone są programowaniu obiektowemu w C++. Znajdziemy tu m.in. objaśnienie tak fundamentalnych pojęć, jak obiekty i klasy (z metodami, konstruktorami i destruktorami), dziedziczenie, hermetyzacja danych i polimorfizm. Rozdział 9. przedstawia sposoby wykorzystywania bibliotek (napisanych w C lub C++) oraz metody dzielenia własnego projektu na wiele plików źródłowych. Rozdział 10. poświęcony jest omówieniu podstawowej koncepcji programowania generycznego, czyli szablonów. Kolejne dwa rozdziały zawierają opis podstawowych elementów bodaj największego osiągnięcia programowania generycznego, czyli wchodzącej w skład stan-

12

Wstęp

dardu C++ biblioteki STL. Ostatni rozdział opisuje metody radzenia sobie z błędami, a w szczególności z tzw. sytuacjami wyjątkowymi. Książkę uzupełnia kilka dodatków. Mając na względzie to, że książka przeznaczona jest głównie dla nowicjuszy, w miarę możliwości starałem się umieszczać w niej pełne wersje programów, a także informacje o efektach ich działania. Starałem się także, by programy te wykonywały nietrywialne, możliwie jak najbardziej „widowiskowe” zadania i by pobudzały do dalszej, samodzielnej pracy. W kilku przypadkach, w celu zaoszczędzenia miejsca, skróciłem niektóre wydruki o deklaracje niemające znaczenia dla zrozumienia działania programu. Przypadki te można łatwo zidentyfikować na podstawie niepełnej numeracji wierszy wydruków. Pełne kody źródłowe wszystkich programów dostępne są na stronie ftp://ftp.helion.pl/przyklady/jcppps.zip. Niniejszy podręcznik powstał w oparciu o moje wieloletnie doświadczenie w nauczaniu C++, a bezpośrednim bodźcem do jego napisania był kurs programowania współfinansowany przez Europejski Fundusz Społeczny – Zintegrowany Program Operacyjny Rozwoju Regionalnego. Inspirację czerpałem też z książek B. Stroustrupa [1], B. Milewskiego [2] i J. Liberty’ego [3]. Pierwsza z nich jest lekturą obowiązkową każdego programisty C++. Na tę jedyną książkę nie warto żałować pieniędzy – po prostu trzeba ją mieć i sięgać po nią możliwie często. Niestety, nie jest to lektura łatwa, nie jest też pomyślana jako podręcznik dla początkujących. Dwie pozostałe cenię za oryginalne podejście pedagogiczne do tematu. Na zakończenie pozwolę sobie jeszcze podziękować Bartoszowi Milewskiemu – mojemu pierwszemu nauczycielowi C++.

Rozdział 1

Pierwszy program w C++ Dla kogo jest ta książka? Rys historyczny. Pierwszy program. Środowisko programistyczne. Kompilator i kompilacja. Błędy kompilacji. Typy int i double, obiekty std::cin i std::cout. Instrukcja using namespace std.

1.1. Dla kogo jest ta książka? Podręcznik napisałem z myślą o osobie pragnącej nauczyć się języka C++ od podstaw. Zakładam, że Czytelnik biegle posługuje się komputerem (np. potrafi zainstalować program lub „odstrzelić” zawieszoną aplikację), ma dostęp do internetu i zna już jakiś język programowania. Oczywiście niezbędna jest też przyzwoita znajomość języka angielskiego – co najmniej w stopniu pozwalającym swobodnie rozumieć komunikaty diagnostyczne kompilatora, a najlepiej na poziomie pozwalającym rozumieć oryginalną dokumentację bibliotek.

1.2. Rys historyczny Dawno, dawno temu, czyli w połowie XX wieku, komputery były bardzo kosztownymi urządzeniami, które wymagały niezwykle pracochłonnej obsługi. W tych zamierzchłych czasach to ludzie dostosowywali się do możliwości maszyn cyfrowych i obsługiwali je, wpisując programy jako ciągi „zer” i „ jedynek” poprzez ręczne ustawienie przekaźników; wyniki obliczeń również otrzymywano jako sekwencje zer i jedynek odczytywanych ze stanu lampek. Nieco później opracowano asemblery – proste języki, które pozwalały pisać programy w bardziej dla ludzi zrozumiałych kategoriach rozkazów, liczb, zmiennych; napisane w nich programy były automatycznie tłumaczone na kod maszynowy – człowiek mógł wreszcie „zapomnieć” o zerach i jedynkach. Następnie pojawiły się języki proceduralne, np. FORTRAN; programy w nich napisane przypominały już wzory matematyczne, były więc całkiem dobrze dostosowane do rozwiązywania wielu problemów technicznych. Wciąż jednak koszt komputerów był ogromny, a ich moc – szczególnie z dzisiejszej perspektywy – bardzo ograniczona. W tych czasach komputery były obsługiwane wyłącznie przez wysoko wykwalifikowany personel, a główną troską programistów było

14

Rozdział 1. Pierwszy program w C++

pisanie programów działających możliwie jak najszybciej i zajmujących jak najmniej zasobów maszyny (głównie pamięci operacyjnej). W tych warunkach nie martwiono się specjalnie kwestią wygody przy obsłudze komputerów – łatwiej i taniej było dostosować ludzi do maszyn niż odwrotnie. Dziś komputery są jednocześnie bardzo szybkie i tanie, a przez to powszechnie dostępne; co więcej, dysponują zasobami sprzętowymi i mocą obliczeniową tysiące lub nawet miliony razy przewyższającymi te dostępne jeszcze trzydzieści lat temu. Typowymi użytkownikami komputerów nie są już wyłącznie błyskotliwi i wszechstronnie wykształceni fachowcy – obecnie komputerami posługują się już nawet przedszkolaki. Ci nowi, nierzadko niepiśmienni użytkownicy wymagają, by komputery wyposażone były w zupełnie inny rodzaj programów – niezawodnych i łatwych w obsłudze. Takie programy są jednak z natury bardzo złożone1 . Ich wytworzenie wymaga zaangażowania dziesiątek, setek, a czasami tysięcy ludzi. Masowy rynek oznacza potencjalnie wielkie zyski, ale też i ogromne koszty oraz ryzyko utraty rynku na rzecz konkurencji. Stąd wynika potrzeba ograniczenia kosztów. Te z kolei najefektywniej jest redukować już podczas pisania programów, co oznacza konieczność wyposażenia programistów w możliwie jak najlepsze „narzędzia produkcji”: edytor (do wprowadzania tekstu), debuger (do wyszukiwania błędów), system kontroli wersji (do zarządzania poprawkami w programach) i – przede wszystkim – język programowania z możliwie najlepszym kompilatorem, czyli programem tłumaczącym programy napisane przez ludzi na kod maszynowy.

1.2.1. Dlaczego C++? W tej sytuacji w latach osiemdziesiątych na scenę wkracza C++. Język ten, zaprojektowany jako obiektowe rozszerzenie języka C, szybko osiągnął status najpopularniejszego niespecjalistycznego języka programowania. Stało się tak dlatego, że pozwala on na zwiększenie wydajności programistów. Szacuje się, że jeden programista stosujący C++ może sobie poradzić z kilkukrotnie większą (w sensie funkcjonalnym) porcją kodu niż jego kolega posługujący się C. Ponadto kod napisany w C++ jest łatwiejszy w utrzymaniu, rozwoju i ponownym wykorzystaniu w innym projekcie; nie ustępuje przy tym prędkością programom napisanym w C. Jakie są główne zalety C++? • C++ umożliwia stosowanie wielu stylów programowania i pracę na wielu poziomach abstrakcji. Można w nim stosować wstawki asemblerowe, a więc programować w języku maszyny; można też programować proceduralnie w stylu takich języków, jak Pascal czy C; można też programować obiektowo, a więc na wysokim poziomie abstrakcji, ułatwiającym programistom myślenie w kategoriach rozwiązywanego przez nich zadania, a nie abstrakcyjnych zer i jedynek. • C++ jest językiem uniwersalnym. Zakres jego zastosowań obejmuje m.in. oprogramowanie odtwarzacza iPod, systemy operacyjne (Windows XP, Symbian), pakiety biurowe (MS Office, OpenOffice), kompilatory (np. maszynę wirtualną HotSpot języka Java), przeglądarki WWW (Firefox, Opera, Internet Explorer), zaawansowane aplikacje graficzne (Adobe Photoshop, Google Earth) i gry (Doom 3, StarCraft). 1 Na

przykład projekt KDE to ponad cztery miliony wierszy kodu, nad którym pracuje ponad ośmiuset programistów i trzystu tłumaczy; tylko w maju 2002 roku dokonano 11 014 zmian w kodzie źródłowym (http://www.kde.org/whatiskde/project.php#factsandfigures).

1.2. Rys historyczny

15

• C++ zawiera mechanizmy ułatwiające wielokrotne wykorzystywanie tego samego kodu. Programy w C++ (tak jak w C) można dzielić na osobne części; części te można następnie wykorzystywać w dowolnym innym programie C++, przy czym taki moduł wystarczy raz skompilować, a następnie tylko dołączać do nowych programów (w ten sposób powstają „biblioteki”). Ponadto w C++ takie moduły można w bardziej naturalny sposób niż w C odseparować od siebie (dzięki hermetyzacji danych i interfejsom), tworząc z nich prawdziwe „czarne skrzynki”. Dzięki tzw. wyjątkom twórcy bibliotek mogą precyzyjnie określić zachowanie się ich kodu w przypadku sytuacji nadzwyczajnych i nawet wymusić określone zachowanie na użytkownikach tych bibliotek. Tak jak w innych językach programowania, w C++ można uniknąć powielania tego samego kodu poprzez zastosowanie funkcji. Ale C++ oferuje dużo więcej – szablony, dzięki którym ten sam kod można stosować do obiektów różnych typów, a także przestrzenie nazw, dzięki którym łatwo jest zarządzać nazwami używanymi w różnych bibliotekach. • C++ jest rozszerzeniem najpopularniejszego języka lat 80. – języka C. Dlatego programy napisane w C++ mają pełny dostęp do wszystkich niezliczonych bibliotek kiedykolwiek napisanych w C. • Kompilator C++ przejmuje na siebie wiele zadań, za realizację których jeszcze niedawno całkowitą odpowiedzialność ponosił programista. Obejmuje to m.in. sprawdzenie, czy zmienne i funkcje używane są zgodne ze swoją deklaracją. Kompilator C++ tak dokładnie analizuje kod źródłowy, że zaleca się nawet, by programy napisane w „czystym” C kompilować kompilatorem C++. • C++ posiada konstrukcje ułatwiające zarządzanie zasobami komputera. Należą do nich m.in. konstruktory, destruktory i wyjątki. Stosując je systematycznie, można zagwarantować np., że z naszego programu nie będzie „wyciekać” pamięć operacyjna. • Programy napisane w C++ są co najmniej równie szybkie, jak te napisane w C. A niekiedy szybsze (np. dzięki szablonom sortowanie jest nieco szybsze w C++ niż w C). • Biblioteki standardowe C++ są bardziej funkcjonalne od ich odpowiedników ze standardowej biblioteki C. Standardowa biblioteka C++ zawiera m.in. wysokopoziomowy typ napisów std::string, który całkowicie zwalnia programistę z troski o to, w jaki sposób napisy są faktycznie interpretowane przez procesor. Podobnie klasa std::vector jest dużo bardziej elastyczna od standardowych tablic języka C, a o czymś takim jak słownik (std::map) możemy w C tylko pomarzyć. Oczywiście C++ ma też wady: • C++ jest trudny zarówno do nauczania, jak i uczenia się. • C++ stanowi poważne wyzwanie dla twórców kompilatorów i programów narzędziowych. W szczególności żaden powszechnie używany kompilator C++ nie jest w 100% zgodny z obowiązującym standardem tego języka. • Ze względu na swój olbrzymi potencjał wynikający z przyjęcia zasady, że żadna cecha C++ nie może ograniczać kreatywności doświadczonych programistów, w niewprawnych rękach C++ jest jak przysłowiowa zapałka w ręku dziecka. • Ze względu na swoją uniwersalność, C++ nie zawiera wielu podstawowych elementów koniecznych do tworzenia współczesnych aplikacji. Są one dostępne za pośrednictwem bibliotek, których opanowanie wymaga dodatkowego nakładu pracy.

16

Rozdział 1. Pierwszy program w C++

1.2.2. C++ a C Jak już wspomniałem, C++ jest rozszerzeniem języka C. Wiele osób wyciąga stąd wniosek, że aby nauczyć się „trudnego” C++, dobrze jest rozpocząć od „łatwego” C. Wniosek ten jest jednak równie fałszywy jak teza, że przed nauką jazdy samochodem należy nauczyć się jeździć rowerem (bo także ma kierownicę, hamulce i koła). Język C wymaga stosowania wielu konstrukcji, których niemal nie używa się w C++. Dlatego programiści obeznani w języku C, aby dobrze opanować C++, muszą oduczyć się wielu nawyków nabytych podczas pracy w C. Jeżeli ostatecznym celem jest C++, nauka C jest marnowaniem czasu!

1.2.3. Aktualny standard języka Na przestrzeni lat język C++ podlegał stopniowej ewolucji. Większość zmian polegała na dodawaniu nowych cech rozszerzających możliwości języka, jednak kilka modyfikacji doprowadziło do niezgodności nowszych wersji języka z wersjami starszymi. Dlatego programy napisane dziesięć lat temu z reguły nie będą spełniać wymagań aktualnego standardu. Z tego samego powodu stare kompilatory C++ nie skompilują większości współczesnych programów. Niniejszy podręcznik opisuje aktualnie obowiązujący standard ISO C++ z 1998 roku z późniejszymi poprawkami. Przedstawiane tu informacje są zasadniczo niezależne od platformy czy konkretnej implementacji kompilatora; kilka odstępstw od tej reguły (związanych z użyciem niestandardowych bibliotek) opatrzono wyraźnym komentarzem ostrzegawczym. Bliższe informacje o planowanych zmianach w standardzie C++ znajdują się w dodatku A.4

1.3. Zanim napiszesz swój pierwszy program 1.3.1. Środowisko programistyczne Programista, jak każdy zawodowiec, potrzebuje specjalistycznego warsztatu pracy. Nie mam tu oczywiście na myśli samego komputera, lecz specjalne programy służące do tworzenia nowych lub ulepszania starych programów. Taki zestaw programów nazywa się środowiskiem programistycznym. Istnieją dwa podstawowe rodzaje środowisk. Pierwsze, typowe dla systemu Unix i jego pochodnych, to po prostu kolekcja oddzielnych programów uruchamianych z powłoki systemowej; do tej grupy należy m.in. używany w tym podręczniku kompilator gcc. Drugi rodzaj środowisk to tzw. zintegrowane środowiska programistyczne (IDE, ang. Integrated Development Environments), w których programista do wszystkich potrzebnych narzędzi ma dostęp z jednego programu sterującego zintegrowanego ze specjalistycznym edytorem; do tej kategorii należą m.in. produkty firm Microsoft (Visual Studio) i Borland (C++ Builder). Zaletą pierwszego rozwiązania jest to, że daje użytkownikom swobodę w sposobie posługiwania się kompilatorem. W szczególności kompilator gcc można łatwo i ściśle zintegrować z wieloma dostępnymi edytorami tekstu (np. emacs czy vim) lub istniejącymi środowiskami zintegrowanymi (np. C++ Builder), można też na jego podstawie zbudować od podstaw zupełnie nowe środowisko typu IDE (np. KDevelop, Anjuta czy Code::Blocks).

18

Rozdział 1. Pierwszy program w C++

1.4. Pierwszy program Oto nasz pierwszy, najprostszy program w C++. Jego celem jest wyświetlenie na ekranie napisu Pierwszy program w C++. Wydruk 1.1. Pierwszy program w C++ 1

5

#include int main() { std:: cout