Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00381 008666 10462812 na godz. na dobę w sumie
Język C++. Kompendium wiedzy - książka
Język C++. Kompendium wiedzy - książka
Autor: Liczba stron: 1296
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-8530-1 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> c++ - programowanie
Porównaj ceny (książka, ebook, audiobook).

Twój przewodnik po C++!

C++ dzielnie broni swojej pozycji na rynku języków programowania. Pomimo silnego naporu języka Java oraz platformy .NET wciąż jest niezastąpiony w wielu dziedzinach. Jeżeli tylko wymagana jest najwyższa wydajność, dostęp do sprzętu oraz przewidywalny czas wykonania, programiści najczęściej wybierają właśnie język C++. Ostatnia wersja standardu — oznaczona numerem 11 — pozwala na jeszcze łatwiejsze pisanie kodu oraz tworzenie szybszych i wydajniejszych programów.

Najnowsze wydanie tej cenionej książki zostało poprawione i uzupełnione o nowości z tej właśnie wersji standardu języka C++. Dowiesz się, jak korzystać ze wskaźników, liczb losowych oraz udoskonalonych kontenerów. Ponadto poznasz najlepsze zastosowanie wyrażeń lambda czy szablonów. Oprócz omówienia nowości znajdziesz tu również szczegółowy przegląd klasycznych elementów języka C++. Pętle, zmienne, tablice, instrukcje warunkowe — to tylko niektóre z omawianych zagadnień. Książka stanowi doskonały podręcznik dla początkujących programistów i świetne rozwinięcie dla programujących w języku C++ na co dzień. Przekonaj się, jak łatwo i przyjemnie możesz opanować ten popularny język oprogramowania.

Dzięki tej książce:

Poznaj nowości C++ 11!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: The C++ Programming Language, 4th Edition Tłumaczenie: Łukasz Piwko ISBN: 978-83-246-8530-1 Authorized translation from the English language edition, entitled: THE C++ PROGRAMMING LANGUAGE, FOURTH EDITION; ISBN 0321563840; by Bjarne Stroustrup; published by Pearson Education, Inc, publishing as Addison Wesley. Copyright © 2013 by Pearson Education. All rights reserved. No part of this book may by reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. Polish language edition published by HELION S.A. Copyright © 2014. 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. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl 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/jcppkw Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Przedmowa Przedmowa do wydania trzeciego Przedmowa do wydania drugiego Przedmowa do wydania pierwszego CZ(cid:125)(cid:165)(cid:109) I. WPROWADZENIE Rozdzia(cid:239) 1. Uwagi do czytelnika 1.1. Struktura ksi(cid:200)(cid:285)ki 1.1.1. Wprowadzenie 1.1.2. Podstawowe narz(cid:218)dzia 1.1.3. Techniki abstrakcji 1.1.4. Biblioteka standardowa 1.1.5. Przyk(cid:239)ady i odwo(cid:239)ania 1.2. Projekt j(cid:218)zyka C++ 1.2.1. Styl programowania 1.2.2. Kontrola typów 1.2.3. Zgodno(cid:258)(cid:202) z j(cid:218)zykiem C 1.2.4. J(cid:218)zyk, biblioteki i systemy 1.3. Nauka j(cid:218)zyka C++ 1.3.1. Programowanie w j(cid:218)zyku C++ 1.3.2. Rady dla programistów C++ 1.3.3. Rady dla programistów C 1.3.4. Rady dla programistów j(cid:218)zyka Java 1.4. Historia 1.4.1. O(cid:258) czasu 1.4.2. Pierwsze lata 1.4.3. Standard z 1998 r. 1.4.4. Standard z 2011 r. 1.4.5. Do czego jest u(cid:285)ywany j(cid:218)zyk C++ 1.5. Rady 1.6. Literatura Spis tre(cid:258)ci 23 27 29 31 33 35 35 36 36 37 39 40 41 43 46 47 48 50 52 53 53 54 55 56 57 59 62 65 67 68 Kup książkęPoleć książkę 4 Spis tre(cid:258)ci Rozdzia(cid:239) 2. Kurs j(cid:218)zyka C++. Podstawy 2.1. Wprowadzenie 2.2. Podstawy 2.2.1. Witaj, (cid:258)wiecie! 2.2.2. Typy, zmienne i arytmetyka 2.2.3. Sta(cid:239)e 2.2.4. Testy i p(cid:218)tle 2.2.5. Wska(cid:283)niki, tablice i p(cid:218)tle 2.3. Typy zdefiniowane przez u(cid:285)ytkownika 2.3.1. Struktury 2.3.2. Klasy 2.3.3. Wyliczenia 2.4. Modu(cid:239)owo(cid:258)(cid:202) 2.4.1. Osobna kompilacja 2.4.2. Przestrzenie nazw 2.4.3. Obs(cid:239)uga b(cid:239)(cid:218)dów 2.5. Pos(cid:239)owie 2.6. Rady Rozdzia(cid:239) 3. Kurs j(cid:218)zyka C++. Techniki abstrakcji 3.1. Wprowadzenie 3.2. Klasy 3.2.1. Typy konkretne 3.2.2. Typy abstrakcyjne 3.2.3. Funkcje wirtualne 3.2.4. Hierarchie klas 3.3. Kopiowanie i przenoszenie 3.3.1. Kopiowanie kontenerów 3.3.2. Przenoszenie kontenerów 3.3.3. Zarz(cid:200)dzanie zasobami 3.3.4. T(cid:239)umienie operacji 3.4. Szablony 3.4.1. Typy parametryzowane 3.4.2. Szablony funkcji 3.4.3. Obiekty funkcyjne 3.4.4. Zmienne szablony 3.4.5. Aliasy 3.5. Rady Rozdzia(cid:239) 4. Kurs j(cid:218)zyka C++. Kontenery i algorytmy 4.1. Biblioteki 4.1.1. Przegl(cid:200)d biblioteki standardowej 4.1.2. Nag(cid:239)ówki i przestrze(cid:241) nazw biblioteki standardowej 4.2. (cid:146)a(cid:241)cuchy 4.3. Strumienie wej(cid:258)cia i wyj(cid:258)cia 4.3.1. Wyj(cid:258)cie 4.3.2. Wej(cid:258)cie 4.3.3. Wej(cid:258)cie i wyj(cid:258)cie typów zdefiniowanych przez u(cid:285)ytkownika 73 73 74 75 76 78 79 80 82 83 84 86 87 88 89 90 93 93 95 95 96 96 101 103 104 108 108 110 112 113 113 114 115 116 118 119 120 121 121 122 123 124 126 126 127 128 Kup książkęPoleć książkę Spis tre(cid:258)ci 4.4. Kontenery 4.4.1. vector 4.4.2. list 4.4.3. map 4.4.4. unordered_map 4.4.5. Przegl(cid:200)d kontenerów 4.5. Algorytmy 4.5.1. U(cid:285)ywanie iteratorów 4.5.2. Typy iteratorów 4.5.3. Iteratory strumieni 4.5.4. Predykaty 4.5.5. Przegl(cid:200)d algorytmów 4.5.6. Algorytmy kontenerowe 4.6. Rady Rozdzia(cid:239) 5. Kurs j(cid:218)zyka C++. Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) i narz(cid:218)dzia 5.1. Wprowadzenie 5.2. Zarz(cid:200)dzanie zasobami 5.2.1. unique_ptr i shared_ptr 5.3. Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) 5.3.1. Zadania i w(cid:200)tki 5.3.2. Przekazywanie argumentów 5.3.3. Zwracanie wyników 5.3.4. Wspólne u(cid:285)ywanie danych 5.3.5. Komunikacja mi(cid:218)dzy zadaniami 5.4. Drobne, ale przydatne narz(cid:218)dzia 5.4.1. Czas 5.4.2. Funkcje typowe 5.4.3. pair i tuple 5.5. Wyra(cid:285)enia regularne 5.6. Matematyka 5.6.1. Funkcje i algorytmy matematyczne 5.6.2. Liczby zespolone 5.6.3. Liczby losowe 5.6.4. Arytmetyka wektorów 5.6.5. Limity liczbowe 5.7. Rady CZ(cid:125)(cid:165)(cid:109) II. PODSTAWOWE NARZ(cid:125)DZIA Rozdzia(cid:239) 6. Typy i deklaracje 6.1. Standard ISO j(cid:218)zyka C++ 6.1.1. Implementacje 6.1.2. Podstawowy (cid:283)ród(cid:239)owy zestaw znaków 6.2. Typy 6.2.1. Typy podstawowe 6.2.2. Typ logiczny 6.2.3. Typy znakowe 6.2.4. Typy ca(cid:239)kowitoliczbowe 6.2.5. Typy zmiennoprzecinkowe 5 129 130 133 134 135 135 137 138 140 140 142 143 143 144 145 145 146 146 148 149 150 150 151 154 157 157 158 160 161 162 162 163 163 165 165 166 167 169 169 171 171 172 172 173 174 179 181 Kup książkęPoleć książkę 6 Spis tre(cid:258)ci 6.2.6. Przedrostki i przyrostki 6.2.7. void 6.2.8. Rozmiary 6.2.9. Wyrównanie 6.3. Deklaracje 6.3.1. Struktura deklaracji 6.3.2. Deklarowanie po kilka nazw 6.3.3. Nazwy 6.3.4. Zakres dost(cid:218)pno(cid:258)ci 6.3.5. Inicjacja 6.3.6. Dedukowanie typu: auto i decltype() 6.4. Obiekty i warto(cid:258)ci 6.4.1. Warto(cid:258)ci lewo- i prawostronne 6.4.2. Cykl istnienia obiektów 6.5. Aliasy typów 6.6. Rady Rozdzia(cid:239) 7. Wska(cid:283)niki, tablice i referencje 7.1. Wprowadzenie 7.2. Wska(cid:283)niki 7.2.1. void* 7.2.2. nullptr 7.3. Tablice 7.3.1. Inicjatory tablic 7.3.2. Litera(cid:239)y (cid:239)a(cid:241)cuchowe 7.4. Wska(cid:283)niki do tablic 7.4.1. Przegl(cid:200)danie tablic 7.4.2. Tablice wielowymiarowe 7.4.3. Przekazywanie tablic 7.5. Wska(cid:283)niki i const 7.6. Wska(cid:283)niki i w(cid:239)asno(cid:258)(cid:202) 7.7. Referencje 7.7.1. Referencje lewostronne 7.7.2. Referencje prawostronne 7.7.3. Referencje do referencji 7.7.4. Wska(cid:283)niki i referencje 7.8. Rady Rozdzia(cid:239) 8. Struktury, unie i wyliczenia 8.1. Wprowadzenie 8.2. Struktury 8.2.1. Uk(cid:239)ad struktur 8.2.2. Nazwy struktur 8.2.3. Struktury a klasy 8.2.4. Struktury a tablice 8.2.5. Ekwiwalencja typów 8.2.6. Stare zwyk(cid:239)e dane 8.2.7. Pola 182 183 183 185 186 188 189 189 191 194 197 200 200 201 202 203 205 205 205 206 207 208 209 210 213 214 217 217 220 221 222 224 227 229 230 232 233 233 234 235 236 237 239 241 241 244 Kup książkęPoleć książkę Spis tre(cid:258)ci 8.3. Unie 8.3.1. Unie a klasy 8.3.2. Anonimowe unie 8.4. Wyliczenia 8.4.1. Klasy wyliczeniowe 8.4.2. Zwyk(cid:239)e wyliczenia 8.4.3. Wyliczenia anonimowe 8.5. Rady Rozdzia(cid:239) 9. Instrukcje 9.1. Wprowadzenie 9.2. Zestawienie instrukcji 9.3. Deklaracje jako instrukcje 9.4. Instrukcje wyboru 9.4.1. Instrukcje if 9.4.2. Instrukcje switch 9.4.3. Deklaracje w warunkach 9.5. Instrukcje iteracyjne 9.5.1. Zakresowe instrukcje for 9.5.2. Instrukcje for 9.5.3. Instrukcje while 9.5.4. Instrukcje do 9.5.5. Ko(cid:241)czenie p(cid:218)tli 9.6. Instrukcje goto 9.7. Komentarze i wci(cid:218)cia 9.8. Rady Rozdzia(cid:239) 10. Wyra(cid:285)enia 10.1. Wprowadzenie 10.2. Kalkulator 10.2.1. Parser 10.2.2. Wej(cid:258)cie 10.2.3. Wej(cid:258)cie niskopoziomowe 10.2.4. Obs(cid:239)uga b(cid:239)(cid:218)dów 10.2.5. Sterownik 10.2.6. Nag(cid:239)ówki 10.2.7. Argumenty wiersza polece(cid:241) 10.2.8. Uwaga na temat stylu 10.3. Zestawienie operatorów 10.3.1. Wyniki 10.3.2. Kolejno(cid:258)(cid:202) wykonywania dzia(cid:239)a(cid:241) 10.3.3. Priorytety operatorów 10.3.4. Obiekty tymczasowe 10.4. Wyra(cid:285)enia sta(cid:239)e 10.4.1. Sta(cid:239)e symboliczne 10.4.2. const w wyra(cid:285)eniach sta(cid:239)ych 10.4.3. Typy litera(cid:239)owe 10.4.4. Argumenty referencyjne 10.4.5. Wyra(cid:285)enia sta(cid:239)e adresowe 7 244 246 247 249 250 253 254 255 257 257 258 259 260 260 261 264 264 265 266 267 267 268 269 269 271 273 273 273 274 278 282 283 284 284 285 286 287 291 292 292 293 295 297 297 297 298 299 Kup książkęPoleć książkę 8 Spis tre(cid:258)ci 10.5. Niejawna konwersja typów 10.5.1. Promocje 10.5.2. Konwersje 10.5.3. Typowe konwersje arytmetyczne 10.6. Rady Rozdzia(cid:239) 11. Operacje wyboru 11.1. Ró(cid:285)ne operatory 11.1.1. Operatory logiczne 11.1.2. Bitowe operatory logiczne 11.1.3. Wyra(cid:285)enia warunkowe 11.1.4. Inkrementacja i dekrementacja 11.2. Pami(cid:218)(cid:202) wolna 11.2.1. Zarz(cid:200)dzanie pami(cid:218)ci(cid:200) 11.2.2. Tablice 11.2.3. Sprawdzanie dost(cid:218)pno(cid:258)ci miejsca w pami(cid:218)ci 11.2.4. Przeci(cid:200)(cid:285)anie operatora new 11.3. Listy 11.3.1. Model implementacji 11.3.2. Listy kwalifikowane 11.3.3. Listy niekwalifikowane 11.4. Wyra(cid:285)enia lambda 11.4.1. Model implementacji 11.4.2. Alternatywy dla lambd 11.4.3. Lista zmiennych 11.4.4. Wywo(cid:239)ywanie i zwracanie warto(cid:258)ci 11.4.5. Typ lambdy 11.5. Jawna konwersja typów 11.5.1. Konstrukcja 11.5.2. Rzutowania nazwane 11.5.3. Rzutowanie w stylu j(cid:218)zyka C 11.5.4. Rzutowanie w stylu funkcyjnym 11.6. Rady Rozdzia(cid:239) 12. Funkcje 12.1. Deklarowanie funkcji 12.1.1. Dlaczego funkcje 12.1.2. Sk(cid:239)adniki deklaracji funkcji 12.1.3. Definiowanie funkcji 12.1.4. Zwracanie warto(cid:258)ci 12.1.5. Funkcje inline 12.1.6. Funkcje constexpr 12.1.7. Funkcje [[noreturn]] 12.1.8. Zmienne lokalne 12.2. Przekazywanie argumentów 12.2.1. Argumenty referencyjne 12.2.2. Argumenty tablicowe 12.2.3. Argumenty listowe 12.2.4. Nieokre(cid:258)lona liczba argumentów 12.2.5. Argumenty domy(cid:258)lne 299 300 300 303 304 305 305 305 306 307 307 309 311 313 314 315 318 318 319 320 322 322 323 325 329 329 330 331 333 334 334 335 337 337 338 338 339 340 342 343 346 346 347 348 350 351 353 356 Kup książkęPoleć książkę Spis tre(cid:258)ci 12.3. Przeci(cid:200)(cid:285)anie funkcji 12.3.1. Automatyczne wybieranie przeci(cid:200)(cid:285)onych funkcji 12.3.2. Przeci(cid:200)(cid:285)anie a typ zwrotny 12.3.3. Przeci(cid:200)(cid:285)anie a zakres 12.3.4. Wybieranie przeci(cid:200)(cid:285)onych funkcji z wieloma argumentami 12.3.5. R(cid:218)czne wybieranie przeci(cid:200)(cid:285)onej funkcji 12.4. Warunki wst(cid:218)pne i ko(cid:241)cowe 12.5. Wska(cid:283)nik do funkcji 12.6. Makra 12.6.1. Kompilacja warunkowa 12.6.2. Makra predefiniowane 12.6.3. Pragmy 12.7. Rady Rozdzia(cid:239) 13. Obs(cid:239)uga wyj(cid:200)tków 13.1. Obs(cid:239)uga b(cid:239)(cid:218)dów 13.1.1. Wyj(cid:200)tki 13.1.2. Tradycyjna obs(cid:239)uga b(cid:239)(cid:218)dów 13.1.3. Niedba(cid:239)a obs(cid:239)uga b(cid:239)(cid:218)dów 13.1.4. Alternatywne spojrzenie na wyj(cid:200)tki 13.1.5. Kiedy nie mo(cid:285)na u(cid:285)ywa(cid:202) wyj(cid:200)tków 13.1.6. Hierarchiczna obs(cid:239)uga b(cid:239)(cid:218)dów 13.1.7. Wyj(cid:200)tki a wydajno(cid:258)(cid:202) 13.2. Gwarancje wyj(cid:200)tków 13.3. Zarz(cid:200)dzanie zasobami 13.3.1. Finalizacja 13.4. Egzekwowanie przestrzegania niezmienników 13.5. Zg(cid:239)aszanie i przechwytywanie wyj(cid:200)tków 13.5.1. Zg(cid:239)aszanie wyj(cid:200)tków 13.5.2. Przechwytywanie wyj(cid:200)tków 13.5.3. Wyj(cid:200)tki a w(cid:200)tki 13.6. Implementacja wektora 13.6.1. Prosty wektor 13.6.2. Jawna reprezentacja pami(cid:218)ci 13.6.3. Przypisywanie 13.6.4. Zmienianie rozmiaru 13.7. Rady Rozdzia(cid:239) 14. Przestrzenie nazw 14.1. Kwestie dotycz(cid:200)ce kompozycji 14.2. Przestrzenie nazw 14.2.1. Bezpo(cid:258)rednia kwalifikacja 14.2.2. Deklaracje using 14.2.3. Dyrektywy using 14.2.4. Wyszukiwanie wg argumentów 14.2.5. Przestrzenie nazw s(cid:200) otwarte 14.3. Modularyzacja i interfejsy 14.3.1. Przestrzenie nazw i modu(cid:239)y 14.3.2. Implementacje 14.3.3. Interfejsy i implementacje 9 358 358 360 360 361 362 362 364 368 370 371 372 372 373 373 374 376 377 378 379 380 381 383 385 388 389 394 394 397 404 405 405 409 411 413 416 419 419 420 422 423 424 425 427 428 430 431 433 Kup książkęPoleć książkę 10 Spis tre(cid:258)ci 14.4. Sk(cid:239)adanie przy u(cid:285)yciu przestrzeni nazw 14.4.1. Wygoda a bezpiecze(cid:241)stwo 14.4.2. Aliasy przestrzeni nazw 14.4.3. Sk(cid:239)adanie przestrzeni nazw 14.4.4. Sk(cid:239)adanie i wybieranie 14.4.5. Przestrzenie nazw a przeci(cid:200)(cid:285)anie 14.4.6. Wersjonowanie 14.4.7. Zagnie(cid:285)d(cid:285)anie przestrzeni nazw 14.4.8. Anonimowe przestrzenie nazw 14.4.9. Nag(cid:239)ówki j(cid:218)zyka C 14.5. Rady Rozdzia(cid:239) 15. Pliki (cid:283)ród(cid:239)owe i programy 15.1. Rozdzielna kompilacja 15.2. Konsolidacja 15.2.1. Nazwy lokalne w plikach 15.2.2. Pliki nag(cid:239)ówkowe 15.2.3. Regu(cid:239)a jednej definicji 15.2.4. Nag(cid:239)ówki z biblioteki standardowej 15.2.5. Konsolidacja z kodem w innym j(cid:218)zyku 15.2.6. Konsolidacja a wska(cid:283)niki do funkcji 15.3. U(cid:285)ywanie plików nag(cid:239)ówkowych 15.3.1. Organizacja z jednym nag(cid:239)ówkiem 15.3.2. Organizacja z wieloma nag(cid:239)ówkami 15.3.3. Stra(cid:285)nicy do(cid:239)(cid:200)czania 15.4. Programy 15.4.1. Inicjacja zmiennych nielokalnych 15.4.2. Inicjacja i wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) 15.4.3. Zamykanie programu 15.5. Rady CZ(cid:125)(cid:165)(cid:109) III. TECHNIKI ABSTRAKCJI Rozdzia(cid:239) 16. Klasy 16.1. Wprowadzenie 16.2. Podstawowe wiadomo(cid:258)ci o klasach 16.2.1. Funkcje sk(cid:239)adowe 16.2.2. Kopiowanie domy(cid:258)lne 16.2.3. Kontrola dost(cid:218)pu 16.2.4. Klasy i struktury 16.2.5. Konstruktory 16.2.6. Konstruktory explicit 16.2.7. Inicjatory wewn(cid:200)trzklasowe 16.2.8. Wewn(cid:200)trzklasowe definicje funkcji 16.2.9. Zmienno(cid:258)(cid:202) 16.2.10. S(cid:239)owo kluczowe this 16.2.11. Dost(cid:218)p do sk(cid:239)adowych 16.2.12. Sk(cid:239)adowe statyczne 16.2.13. Typy sk(cid:239)adowe 435 435 436 436 438 439 441 443 444 444 445 447 447 448 451 451 453 455 456 458 459 459 463 467 468 469 470 470 472 473 475 475 476 477 478 479 480 481 483 485 486 487 490 491 492 494 Kup książkęPoleć książkę Spis tre(cid:258)ci 16.3. Klasy konkretne 16.3.1. Funkcje sk(cid:239)adowe 16.3.2. Funkcje pomocnicze 16.3.3. Przeci(cid:200)(cid:285)anie operatorów 16.3.4. Znaczenie klas konkretnych 16.4. Rady Rozdzia(cid:239) 17. Tworzenie, kasowanie, kopiowanie i przenoszenie 17.1. Wprowadzenie 17.2. Konstruktory i destruktory 17.2.1. Konstruktory i niezmienniki 17.2.2. Destruktory i zasoby 17.2.3. Destruktory klas bazowych i sk(cid:239)adowych klas 17.2.4. Wywo(cid:239)ywanie konstruktorów i destruktorów 17.2.5. Destruktory wirtualne 17.3. Inicjacja obiektów klas 17.3.1. Inicjacja bez konstruktorów 17.3.2. Inicjacja przy u(cid:285)yciu konstruktorów 17.3.3. Konstruktory domy(cid:258)lne 17.3.4. Konstruktory z list(cid:200) inicjacyjn(cid:200) 17.4. Inicjacja sk(cid:239)adowych i bazy 17.4.1. Inicjacja sk(cid:239)adowych 17.4.2. Inicjatory bazy 17.4.3. Delegowanie konstruktorów 17.4.4. Inicjatory wewn(cid:200)trzklasowe 17.4.5. Inicjacja sk(cid:239)adowych statycznych 17.5. Kopiowanie i przenoszenie 17.5.1. Kopiowanie 17.5.2. Przenoszenie 17.6. Generowanie domy(cid:258)lnych operacji 17.6.1. Jawne operacje domy(cid:258)lne 17.6.2. Operacje domy(cid:258)lne 17.6.3. U(cid:285)ywanie operacji domy(cid:258)lnych 17.6.4. Usuwanie funkcji 17.7. Rady Rozdzia(cid:239) 18. Przeci(cid:200)(cid:285)anie operatorów 18.1. Wprowadzenie 18.2. Funkcje operatorowe 18.2.1. Operatory dwu- i jednoargumentowe 18.2.2. Predefiniowane znaczenie operatorów 18.2.3. Operatory i typy zdefiniowane przez u(cid:285)ytkownika 18.2.4. Przekazywanie obiektów 18.2.5. Operatory w przestrzeniach nazw 18.3. Typ reprezentuj(cid:200)cy liczby zespolone 18.3.1. Operatory sk(cid:239)adowe i zewn(cid:218)trzne 18.3.2. Arytmetyka mieszana 18.3.3. Konwersje 18.3.4. Litera(cid:239)y 18.3.5. Funkcje dost(cid:218)powe 18.3.6. Funkcje pomocnicze 11 495 498 500 502 503 504 505 505 507 508 509 510 511 512 513 513 515 517 519 524 524 525 526 527 529 530 530 537 541 541 542 543 547 548 551 551 553 554 555 555 556 557 559 559 560 561 564 565 565 Kup książkęPoleć książkę 12 Spis tre(cid:258)ci 18.4. Konwersja typów 18.4.1. Operatory konwersji 18.4.2. Operatory konwersji explicit 18.4.3. Niejednoznaczno(cid:258)ci 18.5. Rady Rozdzia(cid:239) 19. Operatory specjalne 19.1. Wprowadzenie 19.2. Operatory specjalne 19.2.1. Indeksowanie 19.2.2. Wywo(cid:239)ywanie funkcji 19.2.3. Dereferencja 19.2.4. Inkrementacja i dekrementacja 19.2.5. Alokacja i dezalokacja 19.2.6. Litera(cid:239)y zdefiniowane przez u(cid:285)ytkownika 19.3. Klasa String 19.3.1. Podstawowe operacje 19.3.2. Dost(cid:218)p do znaków 19.3.3. Reprezentacja 19.3.4. Funkcje sk(cid:239)adowe 19.3.5. Funkcje pomocnicze 19.3.6. Sposoby u(cid:285)ycia 19.4. Przyjaciele 19.4.1. Znajdowanie przyjació(cid:239) 19.4.2. Przyjaciele i sk(cid:239)adowe 19.5. Rady Rozdzia(cid:239) 20. Derywacja klas 20.1. Wprowadzenie 20.2. Klasy pochodne 20.2.1. Funkcje sk(cid:239)adowe 20.2.2. Konstruktory i destruktory 20.3. Hierarchie klas 20.3.1. Pola typów 20.3.2. Funkcje wirtualne 20.3.3. Bezpo(cid:258)rednia kwalifikacja 20.3.4. Kontrola przes(cid:239)aniania 20.3.5. U(cid:285)ywanie sk(cid:239)adowych klasy bazowej 20.3.6. Rozlu(cid:283)nienie zasady dotycz(cid:200)cej typów zwrotnych 20.4. Klasy abstrakcyjne 20.5. Kontrola dost(cid:218)pu 20.5.1. Sk(cid:239)adowe chronione 20.5.2. Dost(cid:218)p do klas bazowych 20.5.3. Deklaracje using i kontrola dost(cid:218)pu 20.6. Wska(cid:283)niki do sk(cid:239)adowych 20.6.1. Wska(cid:283)niki do funkcji sk(cid:239)adowych 20.6.2. Wska(cid:283)niki do danych sk(cid:239)adowych 20.6.3. Sk(cid:239)adowe bazy i klasy pochodnej 20.7. Rady 567 567 569 569 571 573 573 573 573 574 576 578 580 581 584 585 585 586 589 591 593 594 596 597 598 599 599 600 602 604 604 605 607 610 610 614 617 619 621 624 625 627 627 628 630 631 631 Kup książkęPoleć książkę Spis tre(cid:258)ci Rozdzia(cid:239) 21. Hierarchie klas 21.1. Wprowadzenie 21.2. Projektowanie hierarchii klas 21.2.1. Dziedziczenie implementacji 21.2.2. Dziedziczenie interfejsu 21.2.3. Alternatywne implementacje 21.2.4. Lokalizowanie tworzenia obiektu 21.3. Wielodziedziczenie 21.3.1. Wiele interfejsów 21.3.2. Wiele klas implementacyjnych 21.3.3. Rozstrzyganie niejednoznaczno(cid:258)ci 21.3.4. Wielokrotne u(cid:285)ycie klasy bazowej 21.3.5. Wirtualne klasy bazowe 21.3.6. Bazy wirtualne a replikowane 21.4. Rady Rozdzia(cid:239) 22. Informacje o typach w czasie dzia(cid:239)ania programu 22.1. Wprowadzenie 22.2. Poruszanie si(cid:218) w obr(cid:218)bie hierarchii klas 22.2.1. Rzutowanie dynamiczne 22.2.2. Wielodziedziczenie 22.2.3. Rzutowanie statyczne i dynamiczne 22.2.4. Odzyskiwanie interfejsu 22.3. Podwójny polimorfizm i wizytatorzy 22.3.1. Podwójny polimorfizm 22.3.2. Wizytatorzy 22.4. Konstrukcja i destrukcja 22.5. Identyfikacja typów 22.5.1. Rozszerzone informacje o typie 22.6. Poprawne i niepoprawne u(cid:285)ywanie RTTI 22.7. Rady Rozdzia(cid:239) 23. Szablony 23.1. Wprowadzenie i przegl(cid:200)d 23.2. Prosty szablon (cid:239)a(cid:241)cucha 23.2.1. Definiowanie szablonu 23.2.2. Konkretyzacja szablonu 23.3. Kontrola typów 23.3.1. Ekwiwalencja typów 23.3.2. Wykrywanie b(cid:239)(cid:218)dów 23.4. Sk(cid:239)adowe szablonu klasy 23.4.1. Dane sk(cid:239)adowe 23.4.2. Funkcje sk(cid:239)adowe 23.4.3. Aliasy typów sk(cid:239)adowych 23.4.4. Sk(cid:239)adowe statyczne 23.4.5. Typy sk(cid:239)adowe 23.4.6. Szablony sk(cid:239)adowe 23.4.7. Przyjaciele 13 633 633 633 634 637 639 642 644 644 644 646 649 651 655 658 659 659 660 661 664 665 667 670 671 673 675 675 677 678 680 681 681 684 685 687 688 689 690 691 691 692 692 692 693 694 698 Kup książkęPoleć książkę 14 Spis tre(cid:258)ci 23.5. Szablony funkcji 23.5.1. Argumenty szablonu funkcji 23.5.2. Dedukcja argumentów szablonu funkcji 23.5.3. Przeci(cid:200)(cid:285)anie szablonów funkcji 23.6. Aliasy szablonów 23.7. Organizacja kodu (cid:283)ród(cid:239)owego 23.7.1. Konsolidacja 23.8. Rady Rozdzia(cid:239) 24. Programowanie ogólne 24.1. Wprowadzenie 24.2. Algorytmy i uogólnianie 24.3. Koncepcje 24.3.1. Odkrywanie koncepcji 24.3.2. Koncepcje i ograniczenia 24.4. Konkretyzacja koncepcji 24.4.1. Aksjomaty 24.4.2. Koncepcje wieloargumentowe 24.4.3. Koncepcje warto(cid:258)ci 24.4.4. Sprawdzanie ogranicze(cid:241) 24.4.5. Sprawdzanie definicji szablonu 24.5. Rady Rozdzia(cid:239) 25. Specjalizacja 25.1. Wprowadzenie 25.2. Argumenty i parametry szablonu 25.2.1. Typy jako argumenty 25.2.2. Warto(cid:258)ci jako argumenty 25.2.3. Operacje jako argumenty 25.2.4. Szablony jako argumenty 25.2.5. Domy(cid:258)lne argumenty szablonów 25.3. Specjalizacja 25.3.1. Specjalizacja interfejsu 25.3.2. Szablon podstawowy 25.3.3. Porz(cid:200)dek specjalizacji 25.3.4. Specjalizacja szablonu funkcji 25.4. Rady Rozdzia(cid:239) 26. Konkretyzacja 26.1. Wprowadzenie 26.2. Konkretyzacja szablonu 26.2.1. Kiedy konkretyzacja jest potrzebna 26.2.2. R(cid:218)czne sterowanie konkretyzacj(cid:200) 26.3. Wi(cid:200)zanie nazw 26.3.1. Nazwy zale(cid:285)ne 26.3.2. Wi(cid:200)zanie w miejscu definicji 26.3.3. Wi(cid:200)zanie w miejscu konkretyzacji 26.3.4. Wiele miejsc konkretyzacji 699 701 702 704 708 709 711 712 713 713 714 718 718 722 724 727 728 729 730 731 733 735 735 736 736 738 739 742 742 744 747 748 750 750 753 755 755 756 757 758 759 761 762 763 766 Kup książkęPoleć książkę Spis tre(cid:258)ci 26.3.5. Szablony i przestrzenie nazw 26.3.6. Nadmiernie agresywne wyszukiwanie wg argumentów 26.3.7. Nazwy z klas bazowych 26.4. Rady Rozdzia(cid:239) 27. Hierarchie szablonów 27.1. Wprowadzenie 27.2. Parametryzacja i hierarchia 27.2.1. Typy generowane 27.2.2. Konwersje szablonów 27.3. Hierarchie szablonów klas 27.3.1. Szablony jako interfejsy 27.4. Parametry szablonowe jako klasy bazowe 27.4.1. Sk(cid:239)adanie struktur danych 27.4.2. Linearyzacja hierarchii klas 27.5. Rady Rozdzia(cid:239) 28. Metaprogramowanie 28.1. Wprowadzenie 28.2. Funkcje typowe 28.2.1. Aliasy typów 28.2.2. Predykaty typów 28.2.3. Wybieranie funkcji 28.2.4. Cechy 28.3. Struktury steruj(cid:200)ce 28.3.1. Wybieranie 28.3.2. Iteracja i rekurencja 28.3.3. Kiedy stosowa(cid:202) metaprogramowanie 28.4. Definicja warunkowa 28.4.1. U(cid:285)ywanie Enable_if 28.4.2. Implementacja Enable_if 28.4.3. Enable_if i koncepcje 28.4.4. Dodatkowe przyk(cid:239)ady u(cid:285)ycia Enable_if 28.5. Lista czasu kompilacji 28.5.1. Prosta funkcja wyj(cid:258)ciowa 28.5.2. Dost(cid:218)p do elementów 28.5.3. make_tuple 28.6. Szablony zmienne 28.6.1. Bezpieczna typowo funkcja printf() 28.6.2. Szczegó(cid:239)y techniczne 28.6.3. Przekazywanie 28.6.4. Typ tuple z biblioteki standardowej 28.7. Przyk(cid:239)ad z jednostkami uk(cid:239)adu SI 28.7.1. Jednostki 28.7.2. Wielko(cid:258)ci 28.7.3. Litera(cid:239)y jednostkowe 28.7.4. Funkcje pomocnicze 28.8. Rady 15 767 768 770 772 773 773 774 776 778 779 780 781 781 785 790 791 791 794 796 798 799 800 802 802 805 806 807 809 811 811 812 814 816 818 820 821 821 824 825 827 830 830 831 833 834 836 Kup książkęPoleć książkę 16 Spis tre(cid:258)ci Rozdzia(cid:239) 29. Projekt macierzy 29.1. Wprowadzenie 29.1.1. Podstawowe zastosowania macierzy 29.1.2. Wymagania dotycz(cid:200)ce macierzy 29.2. Szablon macierzy 29.2.1. Konstrukcja i przypisywanie 29.2.2. Indeksowanie i ci(cid:218)cie 29.3. Operacje arytmetyczne na macierzach 29.3.1. Operacje skalarne 29.3.2. Dodawanie 29.3.3. Mno(cid:285)enie 29.4. Implementacja macierzy 29.4.1. Wycinki 29.4.2. Wycinki macierzy 29.4.3. Matrix_ref 29.4.4. Inicjacja listy macierzy 29.4.5. Dost(cid:218)p do macierzy 29.4.6. Macierz zerowymiarowa 29.5. Rozwi(cid:200)zywanie równa(cid:241) liniowych 29.5.1. Klasyczna eliminacja Gaussa 29.5.2. Znajdowanie elementu centralnego 29.5.3. Testowanie 29.5.4. Po(cid:239)(cid:200)czone operacje 29.6. Rady CZ(cid:125)(cid:165)(cid:109) IV. BIBLIOTEKA STANDARDOWA Rozdzia(cid:239) 30. Przegl(cid:200)d zawarto(cid:258)ci biblioteki standardowej 30.1. Wprowadzenie 30.1.1. Narz(cid:218)dzia biblioteki standardowej 30.1.2. Kryteria projektowe 30.1.3. Styl opisu 30.2. Nag(cid:239)ówki 30.3. Wsparcie dla j(cid:218)zyka 30.3.1. Wsparcie dla list inicjacyjnych 30.3.2. Wsparcie dla zakresowej p(cid:218)tli for 30.4. Obs(cid:239)uga b(cid:239)(cid:218)dów 30.4.1. Wyj(cid:200)tki 30.4.2. Asercje 30.4.3. system_error 30.5. Rady Rozdzia(cid:239) 31. Kontenery STL 31.1. Wprowadzenie 31.2. Przegl(cid:200)d kontenerów 31.2.1. Reprezentacja kontenera 31.2.2. Wymagania dotycz(cid:200)ce elementów 837 837 838 840 841 842 843 845 846 847 848 850 850 850 852 853 855 857 858 859 860 861 862 864 865 867 867 868 869 870 871 875 876 876 877 877 882 882 892 893 893 893 896 898 Kup książkęPoleć książkę Spis tre(cid:258)ci 31.3. Przegl(cid:200)d operacji 31.3.1. Typy sk(cid:239)adowe 31.3.2. Konstruktory, destruktory i przypisania 31.3.3. Rozmiar i pojemno(cid:258)(cid:202) 31.3.4. Iteratory 31.3.5. Dost(cid:218)p do elementów 31.3.6. Operacje stosowe 31.3.7. Operacje listowe 31.3.8. Inne operacje 31.4. Kontenery 31.4.1. vector 31.4.2. Listy 31.4.3. Kontenery asocjacyjne 31.5. Adaptacje kontenerów 31.5.1. Stos 31.5.2. Kolejka 31.5.3. Kolejka priorytetowa 31.6. Rady Rozdzia(cid:239) 32. Algorytmy STL 32.1. Wprowadzenie 32.2. Algorytmy 32.2.1. Sekwencje 32.3. Argumenty zasad 32.3.1. Z(cid:239)o(cid:285)ono(cid:258)(cid:202) 32.4. Algorytmy nie modyfikuj(cid:200)ce sekwencji 32.4.1. for_each() 32.4.2. Predykaty sekwencji 32.4.3. count() 32.4.4. find() 32.4.5. equal() i mismatch() 32.4.6. search() 32.5. Algorytmy modyfikuj(cid:200)ce sekwencje 32.5.1. copy() 32.5.2. unique() 32.5.3. remove() i replace() 32.5.4. rotate(), random_shuffle() oraz partition() 32.5.5. Permutacje 32.5.6. fill() 32.5.7. swap() 32.6. Sortowanie i wyszukiwanie 32.6.1. Wyszukiwanie binarne 32.6.2. merge() 32.6.3. Algorytmy dzia(cid:239)aj(cid:200)ce na zbiorach 32.6.4. Sterty 32.6.5. lexicographical_compare() 32.7. Element minimalny i maksymalny 32.8. Rady 17 901 904 904 906 907 908 908 909 910 910 911 915 917 929 929 931 931 932 935 935 935 936 938 939 940 940 940 940 941 942 942 943 944 945 946 947 948 948 949 950 952 954 954 955 956 957 958 Kup książkęPoleć książkę 18 Spis tre(cid:258)ci Rozdzia(cid:239) 33. Iteratory STL 33.1. Wprowadzenie 33.1.1. Model iteratorów 33.1.2. Kategorie iteratorów 33.1.3. Cechy iteratorów 33.1.4. Operacje iteratorów 33.2. Adaptacje iteratorów 33.2.1. Iterator odwrotny 33.2.2. Iteratory wstawiaj(cid:200)ce 33.2.3. Iteratory przenosz(cid:200)ce 33.3. Zakresowe funkcje dost(cid:218)powe 33.4. Obiekty funkcyjne 33.5. Adaptacje funkcji 33.5.1. bind() 33.5.2. mem_fn() 33.5.3. function 33.6. Rady Rozdzia(cid:239) 34. Pami(cid:218)(cid:202) i zasoby 34.1. Wprowadzenie 34.2. „Prawie kontenery” 34.2.1. array 34.2.2. bitset 34.2.3. vector bool 34.2.4. Krotki 34.3. Wska(cid:283)niki do zarz(cid:200)dzania pami(cid:218)ci(cid:200) 34.3.1. unique_ptr 34.3.2. shared_ptr 34.3.3. weak_ptr 34.4. Alokatory 34.4.1. Alokator domy(cid:258)lny 34.4.2. Cechy alokatorów 34.4.3. Cechy wska(cid:283)ników 34.4.4. Alokatory zakresowe 34.5. Interfejs od(cid:258)miecacza 34.6. Pami(cid:218)(cid:202) niezainicjowana 34.6.1. Bufory tymczasowe 34.6.2. raw_storage_iterator 34.7. Rady Rozdzia(cid:239) 35. Narz(cid:218)dzia pomocnicze 35.1. Wprowadzenie 35.2. Czas 35.2.1. duration 35.2.2. time_point 35.2.3. Zegary 35.2.4. Cechy czasu 35.3. Dzia(cid:239)ania arytmetyczne na liczbach wymiernych w czasie kompilacji 959 959 959 961 962 964 965 966 968 969 970 971 972 972 974 974 976 977 977 977 978 981 985 986 990 990 993 996 998 1000 1001 1002 1003 1004 1007 1007 1008 1009 1011 1011 1011 1012 1015 1017 1018 1019 Kup książkęPoleć książkę Spis tre(cid:258)ci 35.4. Funkcje typowe 35.4.1. Cechy typów 35.4.2. Generatory typów 35.5. Drobne narz(cid:218)dzia 35.5.1. move() i forward() 35.5.2. swap() 35.5.3. Operatory relacyjne 35.5.4. Porównywanie i mieszanie type_info 35.6. Rady Rozdzia(cid:239) 36. (cid:146)a(cid:241)cuchy 36.1. Wprowadzenie 36.2. Klasyfikacja znaków 36.2.1. Funkcje klasyfikacji 36.2.2. Cechy znaków 36.3. (cid:146)a(cid:241)cuchy 36.3.1. Typ string a (cid:239)a(cid:241)cuchy w stylu C 36.3.2. Konstruktory 36.3.3. Operacje podstawowe 36.3.4. (cid:146)a(cid:241)cuchowe wej(cid:258)cie i wyj(cid:258)cie 36.3.5. Konwersje numeryczne 36.3.6. Operacje w stylu biblioteki STL 36.3.7. Rodzina funkcji find 36.3.8. Pod(cid:239)a(cid:241)cuchy 36.4. Rady Rozdzia(cid:239) 37. Wyra(cid:285)enia regularne 37.1. Wyra(cid:285)enia regularne 37.1.1. Notacja wyra(cid:285)e(cid:241) regularnych 37.2. regex 37.2.1. Wyniki dopasowywania 37.2.2. Formatowanie 37.3. Funkcje wyra(cid:285)e(cid:241) regularnych 37.3.1. regex_match() 37.3.2. regex_search() 37.3.3. regex_replace() 37.4. Iteratory wyra(cid:285)e(cid:241) regularnych 37.4.1. regex_iterator 37.4.2. regex_token_iterator 37.5. regex_traits 37.6. Rady Rozdzia(cid:239) 38. Strumienie wej(cid:258)cia i wyj(cid:258)cia 38.1. Wprowadzenie 38.2. Hierarchia strumieni wej(cid:258)cia i wyj(cid:258)cia 38.2.1. Strumienie plikowe 38.2.2. Strumienie (cid:239)a(cid:241)cuchowe 38.3. Obs(cid:239)uga b(cid:239)(cid:218)dów 19 1020 1020 1025 1030 1030 1031 1031 1032 1033 1035 1035 1035 1035 1036 1038 1039 1040 1042 1044 1044 1046 1048 1049 1050 1053 1053 1054 1059 1061 1063 1064 1064 1066 1067 1068 1068 1070 1072 1073 1075 1075 1077 1078 1079 1081 Kup książkęPoleć książkę 20 Spis tre(cid:258)ci 38.4. Operacje wej(cid:258)cia i wyj(cid:258)cia 38.4.1. Operacje wej(cid:258)ciowe 38.4.2. Operacje wyj(cid:258)ciowe 38.4.3. Manipulatory 38.4.4. Stan strumienia 38.4.5. Formatowanie 38.5. Iteratory strumieniowe 38.6. Buforowanie 38.6.1. Strumienie wyj(cid:258)ciowe i bufory 38.6.2. Strumienie wej(cid:258)ciowe i bufory 38.6.3. Iteratory buforów 38.7. Rady Rozdzia(cid:239) 39. Lokalizacje 39.1. Ró(cid:285)nice kulturowe 39.2. Klasa locale 39.2.1. Lokalizacje nazwane 39.2.2. Porównywanie (cid:239)a(cid:241)cuchów 39.3. Klasa facet 39.3.1. Dost(cid:218)p do faset w lokalizacji 39.3.2. Definiowanie prostej fasety 39.3.3. Zastosowania lokalizacji i faset 39.4. Standardowe fasety 39.4.1. Porównywanie (cid:239)a(cid:241)cuchów 39.4.2. Formatowanie liczb 39.4.3. Formatowanie kwot pieni(cid:218)(cid:285)nych 39.4.4. Formatowanie daty i godziny 39.4.5. Klasyfikacja znaków 39.4.6. Konwersja kodów znaków 39.4.7. Wiadomo(cid:258)ci 39.5. Interfejsy pomocnicze 39.5.1. Klasyfikacja znaków 39.5.2. Konwersje znaków 39.5.3. Konwersje (cid:239)a(cid:241)cuchów 39.5.4. Buforowanie konwersji 39.6. Rady Rozdzia(cid:239) 40. Liczby 40.1. Wprowadzenie 40.2. Granice liczbowe 40.2.1. Makra ograniczaj(cid:200)ce 40.3. Standardowe funkcje matematyczne 40.4. Liczby zespolone 40.5. Tablica numeryczna valarray 40.5.1. Konstruktory i przypisania 40.5.2. Indeksowanie 40.5.3. Operacje 40.5.4. Wycinki 40.5.5. slice_array 40.5.6. Uogólnione wycinki 1082 1083 1086 1088 1089 1094 1101 1102 1105 1106 1107 1109 1111 1111 1114 1116 1120 1120 1121 1122 1125 1125 1127 1131 1136 1141 1144 1147 1151 1155 1155 1156 1156 1157 1158 1159 1159 1160 1162 1163 1164 1166 1166 1168 1169 1172 1174 1175 Kup książkęPoleć książkę Spis tre(cid:258)ci 40.6. Uogólnione algorytmy numeryczne 40.6.1. Algorytm accumulate() 40.6.2. Algorytm inner_product() 40.6.3. Algorytmy partial_sum() i adjacent_difference() 40.6.4. Algorytm iota() 40.7. Liczby losowe 40.7.1. Mechanizmy 40.7.2. Urz(cid:200)dzenie losowe 40.7.3. Rozk(cid:239)ady 40.7.4. Losowanie liczb w stylu C 40.8. Rady Rozdzia(cid:239) 41. Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) 41.1. Wprowadzenie 41.2. Model pami(cid:218)ci 41.2.1. Lokalizacje pami(cid:218)ci 41.2.2. Zmienianie kolejno(cid:258)ci instrukcji 41.2.3. Porz(cid:200)dek pami(cid:218)ci 41.2.4. Wy(cid:258)cigi do danych 41.3. Konstrukcje atomowe 41.3.1. Typy atomowe 41.3.2. Flagi i bariery 41.4. S(cid:239)owo kluczowe volatile 41.5. Rady Rozdzia(cid:239) 42. W(cid:200)tki i zadania 42.1. Wprowadzenie 42.2. W(cid:200)tki 42.2.1. To(cid:285)samo(cid:258)(cid:202) 42.2.2. Konstrukcja 42.2.3. Destrukcja 42.2.4. Funkcja join() 42.2.5. Funkcja detach() 42.2.6. Przestrze(cid:241) nazw this_thread 42.2.7. Likwidowanie w(cid:200)tku 42.2.8. Dane lokalne w(cid:200)tku 42.3. Unikanie wy(cid:258)cigów do danych 42.3.1. Muteksy 42.3.2. Wiele blokad 42.3.3. Funkcja call_once() 42.3.4. Zmienne warunkowe 42.4. Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) zadaniowa 42.4.1. Typy future i promise 42.4.2. Typ promise 42.4.3. Typ packaged_task 42.4.4. Typ future 42.4.5. Typ shared_future 42.4.6. Funkcja async() 42.4.7. Przyk(cid:239)ad równoleg(cid:239)ej funkcji find() 42.5. Rady 21 1176 1177 1177 1178 1179 1180 1182 1184 1185 1189 1189 1191 1191 1193 1194 1195 1196 1197 1198 1201 1205 1207 1207 1209 1209 1210 1211 1212 1213 1214 1215 1217 1218 1218 1220 1220 1228 1230 1231 1235 1236 1237 1238 1241 1244 1245 1247 1251 Kup książkęPoleć książkę 22 Spis tre(cid:258)ci Rozdzia(cid:239) 43. Biblioteka standardowa C 43.1. Wprowadzenie 43.2. Pliki 43.3. Rodzina printf() 43.4. (cid:146)a(cid:241)cuchy w stylu C 43.5. Pami(cid:218)(cid:202) 43.6. Data i godzina 43.7. Itd. 43.8. Rady Rozdzia(cid:239) 44. Zgodno(cid:258)(cid:202) 44.1. Wprowadzenie 44.2. Rozszerzenia C++11 44.2.1. Narz(cid:218)dzia j(cid:218)zykowe 44.2.2. Sk(cid:239)adniki biblioteki standardowej 44.2.3. Elementy wycofywane 44.2.4. Praca ze starszymi implementacjami C++ 44.3. Zgodno(cid:258)(cid:202) C i C++ 44.3.1. C i C++ to rodze(cid:241)stwo 44.3.2. „Ciche” ró(cid:285)nice 44.3.3. Kod C nie b(cid:218)d(cid:200)cy kodem C++ 44.3.4. Kod C++ nie b(cid:218)d(cid:200)cy kodem C 44.4. Rady Skorowidz 1253 1253 1253 1254 1259 1260 1261 1264 1266 1267 1267 1268 1268 1269 1270 1271 1271 1271 1273 1274 1277 1279 1281 Kup książkęPoleć książkę 10 Wyra(cid:285)enia Programowanie jest jak seks: mo(cid:285)e dawa(cid:202) konkretne wyniki, ale nie po to si(cid:218) to robi — przeprosiny dla Richarda Feynmana (cid:120) Wprowadzenie (cid:120) Kalkulator Parser; Wej(cid:258)cie; Wej(cid:258)cie niskopoziomowe; Obs(cid:239)uga b(cid:239)(cid:218)dów; Sterownik; Nag(cid:239)ówki; Argumenty wiersza polece(cid:241); Uwaga na temat stylu (cid:120) Zestawienie operatorów Wyniki; Kolejno(cid:258)(cid:202) wykonywania dzia(cid:239)a(cid:241); Kolejno(cid:258)(cid:202) wykonywania operatorów; Obiekty tymczasowe (cid:120) Wyra(cid:285)enia sta(cid:239)e Sta(cid:239)e symboliczne; const w wyra(cid:285)eniach sta(cid:239)ych; Typy litera(cid:239)owe; Argumenty referen- cyjne; Wyra(cid:285)enia sta(cid:239)e adresowe (cid:120) Niejawna konwersja typów Promocje; Konwersje; Typowe konwersje arytmetyczne (cid:120) Rady 10.1. Wprowadzenie W tym rozdziale znajduje si(cid:218) szczegó(cid:239)owy opis w(cid:239)a(cid:258)ciwo(cid:258)ci wyra(cid:285)e(cid:241). W j(cid:218)zyku C++ wyra(cid:285)e- niem jest przypisanie, wywo(cid:239)anie funkcji, utworzenie obiektu, jak równie(cid:285) wiele innych ope- racji wykraczaj(cid:200)cych daleko poza konwencjonalne obliczanie wyra(cid:285)e(cid:241) arytmetycznych. Aby pokaza(cid:202), w jaki sposób u(cid:285)ywa si(cid:218) wyra(cid:285)e(cid:241), a tak(cid:285)e przedstawi(cid:202) je w odpowiednim kontek(cid:258)cie, opisa(cid:239)em budow(cid:218) niewielkiego programu — prostego kalkulatora. Dalej przedstawi(cid:239)em ze- stawienie operatorów oraz zwi(cid:218)(cid:283)le opisa(cid:239)em sposób ich dzia(cid:239)ania dla typów wbudowanych. Operatory wymagaj(cid:200)ce bardziej szczegó(cid:239)owego omówienia s(cid:200) opisane w rozdziale 11. 10.2. Kalkulator Wyobra(cid:283) sobie prosty kalkulator s(cid:239)u(cid:285)(cid:200)cy do wykonywania czterech podstawowych dzia(cid:239)a(cid:241) arytmetycznych reprezentowanych przez operatory infiksowe dzia(cid:239)aj(cid:200)ce na liczbach zmien- noprzecinkowych. Na przyk(cid:239)ad dla poni(cid:285)szych danych: Kup książkęPoleć książkę 274 r = 2.5 area = pi*r*r Rozdzia(cid:239) 10 • Wyra(cid:285)enia (warto(cid:258)(cid:202) pi jest zdefiniowana standardowo) program ten zwróci taki wynik: 2.5 19.635 2.5 to wynik dla pierwszej linijki danych wej(cid:258)ciowych, a 19.635 to wynik dla drugiej. Cztery g(cid:239)ówne elementy budowy kalkulatora to: parser, funkcja przyjmowania danych, ta- blica symboli oraz sterownik. W istocie jest to miniaturowy kompilator, w którym parser wy- konuje analiz(cid:218) sk(cid:239)adniow(cid:200), funkcja wej(cid:258)ciowa pobiera dane i wykonuje analiz(cid:218) leksykaln(cid:200), ta- blica symboli przechowuje informacje sta(cid:239)e, a sterownik obs(cid:239)uguje inicjacj(cid:218), wyj(cid:258)cie i b(cid:239)(cid:218)dy. Kalkulator ten mo(cid:285)na by by(cid:239)o wzbogaci(cid:202) o wiele dodatkowych funkcji, ale jego kod i tak ju(cid:285) jest d(cid:239)ugi, a takie dodatki w (cid:285)aden sposób nie przyczyni(cid:239)yby si(cid:218) do lepszego poznania sposobu u(cid:285)ywania j(cid:218)zyka C++. 10.2.1. Parser Poni(cid:285)ej znajduje si(cid:218) gramatyka j(cid:218)zyka rozpoznawanego przez parser: program: end // end oznacza koniec danych wej(cid:258)ciowych expr_list end expr_list: expression print // print jest znakiem nowego wiersza lub (cid:258)rednikiem expression print expr_list expression: expression + term expression (cid:344) term term term: term / primary term*primary primary primar y: number // number jest litera(cid:239)em zmiennoprzecinkowym name // name jest identyfikatorem name = expression (cid:344) primar y ( expression ) Innymi s(cid:239)owy, program jest sekwencj(cid:200) wyra(cid:285)e(cid:241) oddzielonych (cid:258)rednikami. Podstawowymi jed- nostkami wyra(cid:285)enia s(cid:200) liczby, nazwy i operatory *, /, +, - (zarówno jedno-, jak i dwuargumen- towy) oraz = (przypisanie). Nazw nie trzeba deklarowa(cid:202) przed u(cid:285)yciem. Rodzaj analizy, który stosuj(cid:218), nazywa si(cid:218) zst(cid:218)powaniem rekurencyjnym (ang. recursive descent). Jest to popularna i prosta technika przetwarzania kodu od góry do do(cid:239)u. W j(cid:218)zykach programowania takich jak C++, w których wywo(cid:239)ania funkcji s(cid:200) wzgl(cid:218)dnie ma(cid:239)o kosztowne, metoda ta jest dodatkowo bardzo wydajna. Dla ka(cid:285)dej produkcji w gramatyce istnieje funkcja wywo(cid:239)uj(cid:200)ca inne funkcje. Symbole terminalne (np. end, number, + i -) s(cid:200) rozpoznawane przez Kup książkęPoleć książkę 10.2. Kalkulator 275 analizator leksykalny, a symbole nieterminalne rozpoznaj(cid:200) funkcj(cid:218) analizy leksykalnej: expr(), term() i prim(). Gdy oba argumenty wyra(cid:285)enia lub podwyra(cid:285)enia s(cid:200) znane, nast(cid:218)puje obliczenie warto(cid:258)ci. W prawdziwym kompilatorze móg(cid:239)by to by(cid:202) moment wygenerowania kodu. Do obs(cid:239)ugi danych wej(cid:258)ciowych wykorzystywana jest klasa Token_stream zawieraj(cid:200)ca ope- racje wczytywania znaków oraz sk(cid:239)adania z nich tokenów. Innymi s(cid:239)owy, klasa Token_stream zamienia strumienie znaków, takie jak 123.45, w tokeny (Token). Tokeny to pary {rodzaj-tokenu, warto(cid:258)(cid:202)}, jak np. {number,123.45}, gdzie litera(cid:239) 123.45 jest zamieniony na warto(cid:258)(cid:202) zmiennoprze- cinkow(cid:200). G(cid:239)ówne cz(cid:218)(cid:258)ci parsera musz(cid:200) tylko zna(cid:202) nazw(cid:218) strumienia tokenów (Token_stream), ts, oraz móc pobra(cid:202) z niego tokeny. W celu wczytania kolejnego tokenu wywo(cid:239)ywana jest funkcja ts.get(). Aby pobra(cid:202) ostatnio wczytany (bie(cid:285)(cid:200)cy) token, wywo(cid:239)ywana jest funkcja ts.current(). Dodatkow(cid:200) funkcj(cid:200) klasy Token_stream jest ukrywanie prawdziwego (cid:283)ród(cid:239)a znaków. Zoba- czysz, (cid:285)e mog(cid:200) one pochodzi(cid:202) wprost od u(cid:285)ytkownika wpisuj(cid:200)cego je za pomoc(cid:200) klawiatury do strumienia cin, z wiersza polece(cid:241) lub z jakiego(cid:258) innego strumienia wej(cid:258)ciowego (10.2.7). Definicja tokenu jest nast(cid:218)puj(cid:200)ca: enum class Kind : char { name, number, end, plus= + , minus= (cid:344) , mul= * , div= / , print= ; , assign= = , lp= ( , rp= ) }; struct Token { Kind kind; string string_value; double number_value; }; Reprezentowanie ka(cid:285)dego tokenu przez warto(cid:258)(cid:202) ca(cid:239)kowitoliczbow(cid:200) jego znaku jest wygod- nym i wydajnym rozwi(cid:200)zaniem oraz mo(cid:285)e by(cid:202) pomocne dla programistów u(cid:285)ywaj(cid:200)cych de- bugera. Metoda ta dzia(cid:239)a, pod warunkiem (cid:285)e (cid:285)aden znak pojawiaj(cid:200)cy si(cid:218) na wej(cid:258)ciu nie ma warto(cid:258)ci u(cid:285)ytej jako enumerator — a (cid:285)aden znany mi zestaw znaków nie zawiera (cid:285)adnego drukowalnego znaku w postaci jednocyfrowej liczby ca(cid:239)kowitej. Interfejs klasy Token_stream wygl(cid:200)da tak: class Token_stream { public: Token get(); // wczytuje i zwraca nast(cid:218)pny token const Token current(); // ostatnio wczytany token //... }; Implementacja jest przedstawiona w sekcji 10.2.2. Ka(cid:285)da funkcja parsera pobiera argument typu bool (6.2.2), o nazwie get, wskazuj(cid:200)cy, czy konieczne jest wywo(cid:239)anie funkcji Token_stream::get() w celu pobrania nast(cid:218)pnego tokenu. Ka(cid:285)da funkcja parsera oblicza warto(cid:258)(cid:202) „swojego” wyra(cid:285)enia i j(cid:200) zwraca. Funkcja expr() obs(cid:239)uguje dodawanie i odejmowanie. Zawiera jedn(cid:200) p(cid:218)tl(cid:218) znajduj(cid:200)c(cid:200) wyrazy do dodania lub odj(cid:218)cia: double expr(bool get) // dodaje i odejmuje { double left = term(get); for (;;) { // wieczno(cid:258)(cid:202) switch (ts.current().kind) { case Kind::plus: Kup książkęPoleć książkę 276 Rozdzia(cid:239) 10 • Wyra(cid:285)enia left += term(true); break; case Kind::minus: left (cid:344)= term(true); break; default: return left; } } } Funkcja ta sama niewiele robi. Jak typowa wysokopoziomowa funkcja w ka(cid:285)dym wi(cid:218)kszym programie ogranicza si(cid:218) do wywo(cid:239)ywania innych funkcji. Instrukcja switch (2.2.4, 9.4.2) porównuje swój warunek, który jest wpisany w nawiasie za s(cid:239)owem kluczowym switch, ze zbiorem sta(cid:239)ych. Instrukcje break s(cid:239)u(cid:285)(cid:200) do wychodzenia z in- strukcji switch. Je(cid:258)li porównywana warto(cid:258)(cid:202) nie pasuje do (cid:285)adnej z klauzul case, wybierana jest klauzula default. Programista nie musi definiowa(cid:202) tej klauzuli. Zwró(cid:202) uwag(cid:218), (cid:285)e wyra(cid:285)enia takie jak 2-3+4 s(cid:200) zgodnie z gramatyk(cid:200) obliczane jako (2-3)+4. Ta dziwna instrukcja for(;;) to p(cid:218)tla niesko(cid:241)czona (9.5). Alternatywnie mo(cid:285)na te(cid:285) u(cid:285)ywa(cid:202) p(cid:218)tli while(true) w tym samym celu. Wykonanie instrukcji switch jest powtarzane, dopóki nie pojawi si(cid:218) co(cid:258) innego ni(cid:285) + lub -, w którym to przypadku nast(cid:218)puje przej(cid:258)cie do klauzuli default i wykonanie instrukcji return. Operatory += i -= s(cid:239)u(cid:285)(cid:200) do obs(cid:239)ugi dodawania i odejmowania. Zamiast nich mo(cid:285)na by by(cid:239)o bez znaczenia dla dzia(cid:239)ania programu u(cid:285)y(cid:202) wyra(cid:285)e(cid:241) left=left+term(true) i left=left(cid:344)term(true). Jednak wyra(cid:285)enia left+=term(true) i left(cid:344)=term(true) nie do(cid:258)(cid:202), (cid:285)e s(cid:200) krótsze, to na dodatek bardziej bezpo(cid:258)rednio odzwierciedlaj(cid:200) zamiar programisty. Ka(cid:285)dy operator przypisania jest osobnym tokenem leksykalnym, a wi(cid:218)c a + = 1; jest b(cid:239)(cid:218)dem sk(cid:239)adniowym z powodu spacji mi(cid:218)dzy operatorami + i =. W j(cid:218)zyku C++ dla operatorów binarnych dost(cid:218)pne s(cid:200) operatory przypisania: + (cid:344) * / | ˆ Mo(cid:285)na wi(cid:218)c u(cid:285)ywa(cid:202) nast(cid:218)puj(cid:200)cych operatorów przypisania: = += (cid:344)= *= /= = = |= ˆ= = = Operator oznacza reszt(cid:218) z dzielenia. Operatory , | oraz ^ to bitowe operacje logiczne i, lub oraz lub wykluczaj(cid:200)ce. Operatory i to operacje przesuni(cid:218)cia w lewo i prawo. Zestawienie operatorów i opis ich dzia(cid:239)ania znajduje si(cid:218) w podrozdziale 10.3. Dla binarnego operatora @ zastosowanego do argumentów typu wbudowanego wyra(cid:285)enie x@=y oznacza x=x@y, z tym (cid:285)e warto(cid:258)(cid:202) x jest obliczana tylko raz. Funkcja term() obs(cid:239)uguje mno(cid:285)enie i dzielenie w taki sam sposób jak expr() dodawanie i odejmowanie: double term(bool get) // mno(cid:285)y i dzieli { double left = prim(get); for (;;) { switch (ts.current().kind) { case Kind::mul: left*= prim(true); break; Kup książkęPoleć książkę 10.2. Kalkulator 277 case Kind::div: if (auto d = prim(true)) { left /= d; break; } return error( Dzielenie przez 0 ); default: return left; } } } Wynik dzielenia przez zero jest niezdefiniowany i najcz(cid:218)(cid:258)ciej operacja taka ma katastrofalne skutki. Dlatego przed wykonaniem dzielenia sprawdzamy, czy dzielnik nie jest zerem, i w razie potrzeby wywo(cid:239)ujemy funkcj(cid:218) error(). Jej opis znajduje si(cid:218) w sekcji 10.2.4. Zmienna d zosta(cid:239)a wprowadzona do programu dok(cid:239)adnie w miejscu, w którym jest po- trzebna, i od razu jest zainicjowana. Zakres dost(cid:218)pno(cid:258)ci nazwy wprowadzonej w warunku obejmuje instrukcj(cid:218) kontrolowan(cid:200) przez ten warunek, a powsta(cid:239)a warto(cid:258)(cid:202) jest warto(cid:258)ci(cid:200) tego warunku (9.4.3). W konsekwencji dzielenie i przypisanie left/=d s(cid:200) wykonywane tylko wtedy, gdy d nie równa si(cid:218) zero. Funkcja prim() obs(cid:239)uguj(cid:200)ca wyra(cid:285)enia pierwotne jest podobna do funkcji expr() i term(), ale w odró(cid:285)nieniu od nich znajduje si(cid:218) na nieco ni(cid:285)szym poziomie hierarchii wywo(cid:239)a(cid:241) i wyko- nuje troch(cid:218) realnej pracy oraz nie zawiera p(cid:218)tli: double prim(bool get) // obs(cid:239)uguje wyra(cid:285)enia pierwotne { if (get) ts.get(); // wczytuje nast(cid:218)pny token switch (ts.current().kind) { case Kind::number: // sta(cid:239)a zmiennoprzecinkowa { double v = ts.current().number_value; ts.g et(); return v; } case Kind::name: { double v = table[ts.current().string_value]; // znajduje odpowiednik if (ts.get().kind == Kind::assign) v = expr(true); // znaleziono operator =: przypisanie return v; } case Kind::minus: // jednoargumentowy minus return (cid:344)prim(true); case Kind::lp: { auto e = expr(true); if (ts.current().kind != Kind::rp) return error( Oczekiwano ) ); ts.get(); // zjada ) return e; } default: return error( Oczekiwano wyra(cid:285)enia pierwotnego ); } } Kup książkęPoleć książkę 278 Rozdzia(cid:239) 10 • Wyra(cid:285)enia Gdy zostanie znaleziony Token b(cid:218)d(cid:200)cy liczb(cid:200) (tzn. litera(cid:239)em ca(cid:239)kowitoliczbowym lub zmien- noprzecinkowym), jego warto(cid:258)(cid:202) jest umieszczana w sk(cid:239)adowej number_value. Analogicznie, gdy zostanie napotkany Token b(cid:218)d(cid:200)cy nazw(cid:200) (name) — jakakolwiek jest jej definicja; zobacz 10.2.2 i 10.2.3 — jego warto(cid:258)(cid:202) jest umieszczana w sk(cid:239)adowej string_value. Zwró(cid:202) uwag(cid:218), (cid:285)e funkcja prim() zawsze wczytuje o jeden token wi(cid:218)cej, ni(cid:285) potrzebuje do analizy swojego wyra(cid:285)enia pierwotnego. Powodem tego jest fakt, (cid:285)e musi to robi(cid:202) w niektó- rych przypadkach (aby np. sprawdzi(cid:202), czy do nazwy jest co(cid:258) przypisywane), wi(cid:218)c dla zacho- wania spójno(cid:258)ci robi to zawsze. W przypadkach, w których funkcja parsera ma tylko przej(cid:258)(cid:202) do nast(cid:218)pnego tokenu, nie musi u(cid:285)ywa(cid:202) warto(cid:258)ci zwrotnej funkcji ts.get(). Nie ma problemu, bo wynik mo(cid:285)na pobra(cid:202) z ts.current(). Gdyby przeszkadza(cid:239)o mi ignorowanie warto(cid:258)ci zwrot- nej funkcji get(), to albo doda(cid:239)bym funkcj(cid:218) read(), która tylko by aktualizowa(cid:239)a current() bez zwracania warto(cid:258)ci, albo jawnie „wyrzuca(cid:239)bym” wynik: void(ts.get()). Zanim kalkulator w jakikolwiek sposób u(cid:285)yje nazwy, najpierw musi sprawdzi(cid:202), czy jest co(cid:258) do niej przypisywane, czy te(cid:285) jest ona tylko odczytywana. W obu przypadkach trzeba si(cid:218)gn(cid:200)(cid:202) do tablicy symboli. Tablica ta jest map(cid:200) (4.4.3, 31.4.3): map string,double table; To znaczy, (cid:285)e mapa table jest indeksowana typem string, dla którego zwracane s(cid:200) warto(cid:258)ci typu double. Je(cid:258)li na przyk(cid:239)ad u(cid:285)ytkownik wpisze: radius = 6378.388; kalkulator dojdzie do klauzuli case Kind::name i wykona: double v = table[ radius ]; // ... expr() oblicza warto(cid:258)(cid:202) do przypisania... v = 6378.388; Referencja v jest u(cid:285)yta jako uchwyt do warto(cid:258)ci double zwi(cid:200)zanej z radius, podczas gdy funk- cja expr() oblicza warto(cid:258)(cid:202) 6378.388 ze znaków wej(cid:258)ciowych. W rozdzia(cid:239)ach 14. i 15. znajduj(cid:200) si(cid:218) wskazówki na temat organizacji programu jako zbioru modu(cid:239)ów. Ale w tym kalkulatorze deklaracje mo(cid:285)na uporz(cid:200)dkowa(cid:202) tak, (cid:285)e (z jednym wyj(cid:200)t- kiem) ka(cid:285)da wyst(cid:200)pi tylko raz, przed samym jej u(cid:285)yciem. Wyj(cid:200)tkiem jest funkcja expr(), która wywo(cid:239)uje funkcj(cid:218) term(), która wywo(cid:239)uje funkcj(cid:218) prim(), która z kolei wywo(cid:239)uje funkcj(cid:218) expr(). Ten kr(cid:200)g wywo(cid:239)a(cid:241) trzeba jako(cid:258) rozerwa(cid:202). Mo(cid:285)na na przyk(cid:239)ad umie(cid:258)ci(cid:202) deklaracj(cid:218): double expr(bool); przed definicj(cid:200) funkcji prim(). 10.2.2. Wej(cid:258)cie Mechanizm wczytywania danych wej(cid:258)ciowych to cz(cid:218)sto najbardziej skomplikowana cz(cid:218)(cid:258)(cid:202) pro- gramu, bo trzeba wzi(cid:200)(cid:202) pod uwag(cid:218) humory, przyzwyczajenia i rozmaite b(cid:239)(cid:218)dy pope(cid:239)niane przez ludzi. Próby zmuszenia u(cid:285)ytkownika do zachowywania si(cid:218) w sposób bardziej odpowiadaj(cid:200)cy maszynie s(cid:200) zwykle (s(cid:239)usznie) uwa(cid:285)ane za niegrzeczne. Zadaniem niskopoziomowej proce- dury wej(cid:258)ciowej jest wczytanie znaków i z(cid:239)o(cid:285)enie z nich tokenów, którymi nast(cid:218)pnie pos(cid:239)u- guj(cid:200) si(cid:218) procedury dzia(cid:239)aj(cid:200)ce na wy(cid:285)szym poziomie. W opisywanym programie niskopozio- mowa procedura obs(cid:239)ugi wej(cid:258)cia nazywa si(cid:218) td.get(). Pisanie takich funkcji nie jest cz(cid:218)stym zadaniem, bo wiele systemów zawiera standardowe funkcje tego rodzaju. Najpierw jednak musimy zobaczy(cid:202) kompletny kod klasy Token_stream: Kup książkęPoleć książkę 10.2. Kalkulator 279 class Token_stream { public: Token_stream(istream s) : ip{ s}, owns{false} { } Token_stream(istream*p) : ip{p}, owns{true} { } ˜Token_stream() { close(); } Token get(); // wczytuje token i go zwraca Token current(); // ostatnio wczytany token void set_input(istream s) { close(); ip = s; owns=false; } void set_input(istream*p) { close(); ip = p; owns = true; } private: void close() { if (owns) delete ip; } istream*ip; // wska(cid:283)nik do strumienia wej(cid:258)ciowego bool owns; // czy Token_stream jest w(cid:239)a(cid:258)cicielem strumienia istream? Token ct {Kind::end} ; // bie(cid:285)(cid:200)cy token }; Obiekt klasy Token_stream inicjujemy strumieniem wej(cid:258)ciowym (4.3.2, rozdzia(cid:239) 38.), z którego pobierane s(cid:200) znaki. Klasa Token_stream jest zaimplementowana w taki sposób, (cid:285)e staje si(cid:218) w(cid:239)a(cid:258)ci- cielem (i ostatecznie te(cid:285) niszczycielem — 3.2.1.2, 11.2) strumienia istream przekazanego jako wska(cid:283)nik, ale nie strumienia istream przekazanego jako referencja. W tak prostym programie mo(cid:285)e nie trzeba stosowa(cid:202) a(cid:285) tak wyszukanego rozwi(cid:200)zania, ale jest to bardzo przydatna i ogól- na technika wykorzystywana do budowy klas przechowuj(cid:200)cych wska(cid:283)niki do zasobów, które kiedy(cid:258) trzeba usun(cid:200)(cid:202). Klasa Token_stream zawiera trzy warto(cid:258)ci: wska(cid:283)nik do swojego strumienia wej(cid:258)ciowego (ip), warto(cid:258)(cid:202) logiczn(cid:200) (owns) okre(cid:258)laj(cid:200)c(cid:200) w(cid:239)asno(cid:258)(cid:202) strumienia wej(cid:258)ciowego oraz bie(cid:285)(cid:200)cy token (ct). Zmiennej cp nada(cid:239)em warto(cid:258)(cid:202) domy(cid:258)ln(cid:200), bo wydawa(cid:239)o mi si(cid:218), (cid:285)e niezrobienie tego by(cid:239)oby nie w porz(cid:200)dku. Wprawdzie nie powinno si(cid:218) wywo(cid:239)ywa(cid:202) funkcji current() przed get(), ale je(cid:258)li kto(cid:258) to zrobi, to otrzyma poprawny token. Jako warto(cid:258)(cid:202) pocz(cid:200)tkow(cid:200) ct wybra(cid:239)em Kind::end, aby w przypadku niew(cid:239)a(cid:258)ciwego u(cid:285)ycia funkcji current() program nie otrzyma(cid:239) (cid:285)adnej war- to(cid:258)ci, która nie pojawi(cid:239)a si(cid:218) w strumieniu wej(cid:258)ciowym. Funkcj(cid:218) Token_stream::get() przedstawi(cid:218) w dwóch ods(cid:239)onach. Najpierw poka(cid:285)(cid:218) z(cid:239)udnie prost(cid:200) wersj(cid:218), która b(cid:218)dzie mniej przyjazna dla u(cid:285)ytkownika. A nast(cid:218)pnie zmodyfikuj(cid:218) j(cid:200) do mniej eleganckiej, ale za to o wiele (cid:239)atwiejszej w u(cid:285)yciu postaci. Ogólnie zadaniem funkcji get() jest wczytanie znaku, zdecydowanie, do jakiego rodzaju tokenu nale(cid:285)y go u(cid:285)y(cid:202), oraz w razie potrzeby wczytanie wi(cid:218)kszej ilo(cid:258)ci znaków i zwrócenie tokenu reprezentuj(cid:200)cego te wczytane znaki. Pocz(cid:200)tkowe instrukcje wczytuj(cid:200) pierwszy niebia(cid:239)y znak z *ip (strumienia wej(cid:258)ciowego wskazywanego przez ip) do ch i sprawdzaj(cid:200), czy operacja odczytu si(cid:218) powiod(cid:239)a: Token Token_stream::get() { char ch = 0; *ip ch; switch (ch) { case 0: return ct={Kind::end}; // przypisanie i zwrot Kup książkęPoleć książkę 280 Rozdzia(cid:239) 10 • Wyra(cid:285)enia Domy(cid:258)lnie operator pomija bia(cid:239)e znaki (spacje, tabulatory, znaki nowego wiersza itd.) i po- zostawia warto(cid:258)(cid:202) ch niezmienion(cid:200), je(cid:258)li operacja przyjmowania danych si(cid:218) nie powiedzie. W konsekwencji ch==0 oznacza koniec wprowadzania danych. Przypisanie jest operatorem, a jego wynik jest warto(cid:258)ci(cid:200) zmiennej, której dotyczy to przy- pisanie. Dzi(cid:218)ki temu mog(cid:218) przypisa(cid:202) warto(cid:258)(cid:202) Kind::end do curr_tok i zwróci(cid:202) j(cid:200) w tej samej instrukcji. Jedna instrukcja zamiast dwóch u(cid:239)atwia konserwacj(cid:218) kodu. Gdybym rozdzieli(cid:239) przy- pisanie i zwrot, to inny programista móg(cid:239)by zmieni(cid:202) co(cid:258) w jednej cz(cid:218)(cid:258)ci i zapomnie(cid:202) odpo- wiednio dostosowa(cid:202) drug(cid:200). Zwró(cid:202) te(cid:285) uwag(cid:218) na sposób u(cid:285)ycia notacji listowej {} (3.2.1.3, 11.3) po prawej stronie przypisania. Jest to wyra(cid:285)enie. Powy(cid:285)sz(cid:200) instrukcj(cid:218) return mo(cid:285)na by by(cid:239)o napisa(cid:202) równie(cid:285) tak: ct.kind = Kind::end; // przypisanie return ct; // zwrot Uwa(cid:285)am jednak, (cid:285)e przypisanie kompletnego obiektu {Kind::end} jest bardziej zrozumia(cid:239)e ni(cid:285) pos(cid:239)ugiwanie si(cid:218) poszczególnymi sk(cid:239)adowymi ct. Zapis {Kind::end} jest równowa(cid:285)ny z {Kind::end,0,0}. To dobrze, je(cid:258)li interesuj(cid:200) nas dwie ostatnie sk(cid:239)adowe tokenu, i (cid:283)le, je(cid:258)li zale(cid:285)y nam na wydajno(cid:258)ci. Nas w tym przypadku nie dotyczy ani pierwsze, ani drugie, ale ogólnie rzecz bior(cid:200)c, pos(cid:239)ugiwanie si(cid:218) kompletnymi obiektami stwarza mniej okazji do po- pe(cid:239)nienia b(cid:239)(cid:218)du ni(cid:285) grzebanie przy poszczególnych sk(cid:239)adowych. Poni(cid:285)ej przedstawiona jest implementacja tej drugiej strategii. Najpierw przeanalizuj kilka z poni(cid:285)szych klauzul case osobno, a dopiero potem zastanów si(cid:218) nad dzia(cid:239)aniem ca(cid:239)ej funkcji. Znak oznaczaj(cid:200)cy koniec wyra(cid:285)enia (;), nawiasy oraz operatory s(cid:200) obs(cid:239)ugiwane poprzez zwyk(cid:239)e zwracanie ich warto(cid:258)ci: case ; : // koniec wyra(cid:285)enia; drukowanie case * : case / : case + : case (cid:344) : case ( : case ) : case = : return ct={static_cast Kind (ch)}; Operacja static_cast (11.5.2) jest w tym przypadku niezb(cid:218)dna, poniewa(cid:285) nie istnieje niejaw- na konwersja typu char na Kind (8.4.1). Tylko niektóre znaki odpowiadaj(cid:200) warto(cid:258)ciom Kind, wi(cid:218)c musimy zagwarantowa(cid:202) to dla ch. Liczby s(cid:200) obs(cid:239)ugiwane w nast(cid:218)puj(cid:200)cy sposób: case 0 : case 1 : case 2 : case 3 : case 4 : case 5 : case 6 : case 7 : (cid:180)case 8 : case 9 : case . : ip(cid:344) putback(ch); // wstawia pierwsz(cid:200) cyfr(cid:218) (albo .) z powrotem do strumienia wej(cid:258)ciowego *ip ct.number_value; // wczytuje liczb(cid:218) do ct ct.kind=Kind::number; return ct; Wypisanie wszystkich klauzul case w jednej linii zamiast ka(cid:285)dej w osobnym wierszu nie jest dobrym pomys(cid:239)em, bo taki kod jest mniej czytelny. Z drugiej strony, wpisywanie ka(cid:285)dej cyfry w osobnej linijce jest (cid:285)mudne. Dzi(cid:218)ki temu, (cid:285)e operator ju(cid:285) obs(cid:239)uguje wczytywanie liczb zmiennoprzecinkowych do zmiennych typu double, ten kod jest bardzo prosty. Najpierw pierwszy znak (cyfra lub kropka) jest umieszczany w cin. Nast(cid:218)pnie warto(cid:258)(cid:202) zmiennoprze- cinkowa mo(cid:285)e zosta(cid:202) wczytana do ct.number_value. Kup książkęPoleć książkę 10.2. Kalkulator 281 Je(cid:258)li token nie jest ko(cid:241)cem danych wej(cid:258)ciowych ani operatorem, znakiem interpunkcyjnym czy te(cid:285) liczb(cid:200), to musi by(cid:202) nazw(cid:200). Nazwy s(cid:200) obs(cid:239)ugiwane podobnie do liczb: default: // name, name = lub b(cid:239)(cid:200)d if (isalpha(ch)) { ip(cid:344) putback(ch); // umieszcza pierwszy znak z powrotem w strumieniu wej(cid:258)ciowym *ip ct.string_value; // wczytuje (cid:239)a(cid:241)cuch do ct ct.kind=Kind::name; return ct; } W ko(cid:241)cu mo(cid:285)e te(cid:285) wyst(cid:200)pi(cid:202) b(cid:239)(cid:200)d. Proste a zarazem ca(cid:239)kiem efektywne rozwi(cid:200)zanie na pora- dzenie sobie z b(cid:239)(cid:218)dami to napisanie funkcji error() i zwrócenie tokenu print w warto(cid:258)ci zwrotnej tej funkcji: error( Niepoprawny token ); return ct={Kind::print}; Funkcja isalpha() z biblioteki standardowej (36.2.1) zosta(cid:239)a u(cid:285)yta po to, aby unikn(cid:200)(cid:202) ko- nieczno(cid:258)ci wymieniania ka(cid:285)dego znaku w osobnej klauzuli case. Je(cid:258)li operator zostanie za- stosowany do (cid:239)a(cid:241)cucha (w tym przypadku string_value), wczytuje znaki do momentu napo- tkania bia(cid:239)ego znaku. W zwi(cid:200)zku z tym u(cid:285)ytkownik musi po nazwie wpisa(cid:202) bia(cid:239)y znak przed operatorem u(cid:285)ywaj(cid:200)cym tej nazwy jako argumentu. Jest to bardzo s(cid:239)abe rozwi(cid:200)zanie i b(cid:218)dziemy musieli jeszcze do tego wróci(cid:202) w sekcji 10.2.3. Poni(cid:285)ej znajduje si(cid:218) uko(cid:241)czona funkcja wej(cid:258)ciowa: Token Token_stream::g et() { char ch = 0; *ip ch; switch (ch) { case 0: return ct={Kind::end}; // przypisanie i zwrot case ; : // koniec wyra(cid:285)enia; drukuje case * : case / : case + : case (cid:344) : case ( : case ) : case = : return ct=={static_cast Kind (ch)}; case 0 : case 1 : case 2 : case 3 : case 4 : case 5 : case 6 : case 7 : (cid:180)case 8 : case 9 : case . : ip(cid:344) putback(ch); // wstawia pierwsz(cid:200) cyfr(cid:218) (albo .) z powrotem do strumienia wej(cid:258)ciowego *ip ct.number_value; // wczytuje liczb(cid:218) do ct ct.kind=Kind::number; return ct; default: // name, name = lub b(cid:239)(cid:200)d if (isalpha(ch)) { ip(cid:344) putback(ch); // umieszcza pierwszy znak z powrotem w strumieniu wej(cid:258)ciowym *ip ct.string_value; // wczytuje (cid:239)a(cid:241)cuch do ct ct.kind=Kind::name; Kup książkęPoleć książkę 282 Rozdzia(cid:239) 10 • Wyra(cid:285)enia return ct; } error( Niepoprawny token ); return ct={Kind::print}; } } Konwersja operatora na token jest bardzo prosta, bo rodzaje operatorów zosta(cid:239)y zdefiniowane jako warto(cid:258)ci ca(cid:239)kowitoliczbowe (10.2.1). 10.2.3. Wej(cid:258)cie niskopoziomowe W kalkulatorze w obecnej postaci mo(cid:285)na znale(cid:283)(cid:202) kilka niedogodno(cid:258)ci. Trzeba pami(cid:218)ta(cid:202) o do- dawaniu (cid:258)rednika na ko(cid:241)cu wyra(cid:285)e(cid:241), aby otrzyma(cid:202) wynik, oraz po nazwie zawsze trzeba wpisa(cid:202) bia(cid:239)y znak, co równie(cid:285) jest uci(cid:200)(cid:285)liwe. Na przyk(cid:239)ad x+7 jest tylko identyfikatorem, a nie identyfikatorem x, operatorem = i liczb(cid:200) 7. Aby ten zapis zosta(cid:239) zinterpretowany tak, jak by- (cid:258)my tego normalnie chcieli, trzeba by by(cid:239)o doda(cid:202) bia(cid:239)y znak za x: x =7. Oba problemy mo(cid:285)na rozwi(cid:200)za(cid:202) poprzez zamian(cid:218) zorientowanych na typy domy(cid:258)lnych operacji w funkcji get() na kod wczytuj(cid:200)cy pojedyncze znaki. Najpierw zrównamy znaczenie znaku nowego wiersza ze (cid:258)rednikiem oznaczaj(cid:200)cym koniec wyra(cid:285)enia: Token Token_stream::get() { char ch; do { // pomija bia(cid:239)e znaki oprócz if (!ip(cid:344) get(ch)) return ct={Kind::end}; } while (ch!= isspace(ch)); switch (ch) { case ; : case : return ct={Kind::print}; W kodzie tym u(cid:285)y(cid:239)em instrukcji do, która ró(cid:285)ni si(cid:218) od p(cid:218)tli while tylko tym, (cid:285)e kontrolowane przez ni(cid:200) instrukcje s(cid:200) wykonywane przynajmniej raz. Wywo(cid:239)anie ip- get(ch) wczytuje jeden znak ze strumienia wej(cid:258)ciowego *ip do ch.
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Język C++. Kompendium wiedzy
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: