You are on page 1of 27

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl

Thinking in C++.
Edycja polska
Autor: Bruce Eckel
Tumaczenie: Piotr Imiela
ISBN: 83-7197-709-3
Tytu oryginau: Thinking in C++
Format: B5, stron: 642
Przykady na ftp: 247 kB

C++ to jeden z najpopularniejszych jzykw programowania, w ktrym napisano szereg


profesjonalnych aplikacji, a nawet kilka systemw operacyjnych. Nie bez przyczyny
uwaany jest on za trudny do opanowana, stanowic powane wyzwanie zarwno dla
programistw, jak dla autorw podrcznikw.
Wieloletnie dowiadczenie w nauczaniu programowania Bruce'a Eckela gwarantuje,
e po przeczytaniu tej ksiki bdziesz posugiwa si C++ tak sprawnie, jak jzykiem
polskim. Bruce Eckel to nie tylko autor bestsellerowych podrcznikw takich jak:
Thinking in Java, ale rwnie czonek komitetu standaryzujcego C++ i szef firmy
zajmujcy si szkoleniem programistw. Tworzone przez niego kursy programowania
uznawane s za jedne z najlepszych na wiecie.

poznasz podstawowe i zaawansowane techniki programowania w C++


krok po kroku przeledzisz konstrukcj jzyka
nauczysz si diagnozowa i rozwizywa problemy w C++
zwize, atwe do zrozumienia przykady zilustruj przedstawiane zagadnienia
wiczenia utrwal zdobyte umiejtnoci na kadym etapie nauki
kod rdowy zawarty w ksice zgodnie z wieloma kompilorami (w tym
z darmowym kompilatorem GNU C++)

Spis treci
Wstp ............................................................................................. 13
Co nowego w drugim wydaniu?........................................................................................13
Zawarto drugiego tomu ksiki ...............................................................................14
Skd wzi drugi tom ksiki? ...................................................................................14
Wymagania wstpne .........................................................................................................14
Nauka jzyka C++.............................................................................................................15
Cele....................................................................................................................................16
Zawarto rozdziaw .......................................................................................................17
wiczenia ..........................................................................................................................21
Rozwizania wicze..................................................................................................21
Kod rdowy....................................................................................................................21
Standardy jzyka ...............................................................................................................22
Obsuga jzyka............................................................................................................23
Bdy .................................................................................................................................23
Okadka .............................................................................................................................24

Rozdzia 1. Wprowadzenie do obiektw .............................................................. 25


Postp abstrakcji................................................................................................................26
Obiekt posiada interfejs.....................................................................................................27
Ukryta implementacja .......................................................................................................30
Wykorzystywanie istniejcej implementacji.....................................................................31
Dziedziczenie wykorzystywanie istniejcego interfejsu..............................................32
Relacje typu jest i jest podobny do ......................................................................35
Zastpowanie obiektwprzy uyciu polimorfizmu ...........................................................36
Tworzenie i niszczenie obiektw ......................................................................................40
Obsuga wyjtkw sposb traktowania bdw ...........................................................41
Analiza i projektowanie ....................................................................................................42
Etap 0. Przygotuj plan.................................................................................................44
Etap 1. Co tworzymy?.................................................................................................45
Etap 2. Jak to zrobimy?...............................................................................................49
Etap 3. Budujemy jdro ..............................................................................................52
Etap 4. Iteracje przez przypadki uycia ......................................................................53
Etap 5. Ewolucja .........................................................................................................53
Planowanie si opaca .................................................................................................55
Programowanie ekstremalne .............................................................................................55
Najpierw napisz testy..................................................................................................56
Programowanie w parach............................................................................................57
Dlaczego C++ odnosi sukcesy? ........................................................................................58
Lepsze C......................................................................................................................59
Zacze si ju uczy.................................................................................................59

Thinking in C++. Edycja polska


Efektywno................................................................................................................60
Systemy s atwiejsze do opisania i do zrozumienia ..................................................60
Maksymalne wykorzystanie bibliotek ........................................................................60
Wielokrotne wykorzystywanie kodu dziki szablonom .............................................61
Obsuga bdw ..........................................................................................................61
Programowanie na wielk skal..................................................................................61
Strategie przejcia .............................................................................................................62
Wskazwki..................................................................................................................62
Problemy z zarzdzaniem ...........................................................................................64
Podsumowanie ..................................................................................................................66

Rozdzia 2. Tworzeniei uywanie obiektw.......................................................... 67


Proces tumaczenia jzyka ................................................................................................68
Interpretery..................................................................................................................68
Kompilatory ................................................................................................................68
Proces kompilacji........................................................................................................69
Narzdzia do rozcznej kompilacji ..................................................................................71
Deklaracje i definicje ..................................................................................................71
czenie ......................................................................................................................76
Uywanie bibliotek .....................................................................................................76
Twj pierwszy program w C++ ........................................................................................78
Uywanie klasy strumieni wejcia-wyjcia ................................................................78
Przestrzenie nazw........................................................................................................79
Podstawy struktury programu .....................................................................................80
Witaj, wiecie!.........................................................................................................81
Uruchamianie kompilatora..........................................................................................82
Wicej o strumieniach wejcia-wyjcia ............................................................................82
czenie tablic znakowych .........................................................................................83
Odczytywanie wejcia ................................................................................................84
Wywoywanie innych programw..............................................................................84
Wprowadzenie do acuchw ...........................................................................................85
Odczytywanie i zapisywanie plikw.................................................................................86
Wprowadzenie do wektorw.............................................................................................88
Podsumowanie ..................................................................................................................92
wiczenia ..........................................................................................................................93

Rozdzia 3. Jzyk C w C++................................................................................. 95


Tworzenie funkcji .............................................................................................................95
Wartoci zwracane przez funkcje ...............................................................................97
Uywanie bibliotek funkcji jzyka C..........................................................................98
Tworzenie wasnych bibliotekza pomoc programu zarzdzajcego bibliotekami....99
Sterowanie wykonywaniem programu..............................................................................99
Prawda i fasz..............................................................................................................99
if-else.........................................................................................................................100
while..........................................................................................................................101
do-while ....................................................................................................................101
for..............................................................................................................................102
Sowa kluczowe break i continue .............................................................................103
switch ........................................................................................................................104
Uywanie i naduywanie instrukcji goto..................................................................105
Rekurencja ................................................................................................................106
Wprowadzenie do operatorw ........................................................................................107
Priorytety...................................................................................................................107
Automatyczna inkrementacja i dekrementacja .........................................................108

Spis treci

7
Wprowadzenie do typw danych ....................................................................................108
Podstawowe typy wbudowane..................................................................................109
bool, true i false.........................................................................................................110
Specyfikatory ............................................................................................................111
Wprowadzenie do wskanikw ................................................................................112
Modyfikacja obiektw zewntrznych .......................................................................115
Wprowadzenie do referencji .....................................................................................117
Wskaniki i referencje jako modyfikatory................................................................118
Zasig ..............................................................................................................................120
Definiowanie zmiennych w locie ..........................................................................120
Specyfikacja przydziau pamici.....................................................................................122
Zmienne globalne......................................................................................................122
Zmienne lokalne........................................................................................................124
static ..........................................................................................................................124
extern.........................................................................................................................126
Stae...........................................................................................................................127
volatile.......................................................................................................................129
Operatory i ich uywanie ................................................................................................129
Przypisanie................................................................................................................130
Operatory matematyczne ..........................................................................................130
Operatory relacji .......................................................................................................131
Operatory logiczne....................................................................................................131
Operatory bitowe ......................................................................................................132
Operatory przesuni ................................................................................................133
Operatory jednoargumentowe...................................................................................135
Operator trjargumentowy........................................................................................136
Operator przecinkowy...............................................................................................137
Najczstsze puapkizwizane z uywaniem operatorw ..........................................137
Operatory rzutowania................................................................................................138
Jawne rzutowanie w C++..........................................................................................139
sizeof samotny operator .......................................................................................143
Sowo kluczowe asm.................................................................................................143
Operatory dosowne ..................................................................................................144
Tworzenie typw zoonych ...........................................................................................144
Nadawanie typom nowych nazw za pomoc typedef ...............................................144
czenie zmiennych w struktury ..............................................................................145
Zwikszanie przejrzystoci programwza pomoc wylicze ...................................148
Oszczdzanie pamici za pomoc unii .....................................................................150
Tablice.......................................................................................................................151
Wskazwki dotyczce uruchamiania programw...........................................................159
Znaczniki uruchomieniowe.......................................................................................160
Przeksztacanie zmiennych i wyrae w acuchy ...................................................162
Makroinstrukcja assert( ) jzyka C ...........................................................................162
Adresy funkcji .................................................................................................................163
Definicja wskanika do funkcji ................................................................................163
Skomplikowane deklaracje i definicje ......................................................................164
Wykorzystywanie wskanikw do funkcji ...............................................................165
Tablice wskanikw do funkcji ................................................................................166
Make zarzdzanie rozczn kompilacj....................................................................167
Dziaanie programu make .........................................................................................168
Pliki makefile uywane w ksice ............................................................................171
Przykadowy plik makefile .......................................................................................171
Podsumowanie ................................................................................................................173
wiczenia ........................................................................................................................173

Thinking in C++. Edycja polska

Rozdzia 4. Abstrakcja danych ......................................................................... 179


Miniaturowa biblioteka w stylu C...................................................................................180
Dynamiczny przydzia pamici.................................................................................183
Bdne zaoenia .......................................................................................................186
Na czym polega problem?...............................................................................................188
Podstawowy obiekt .........................................................................................................188
Czym s obiekty? ............................................................................................................194
Tworzenieabstrakcyjnych typw danych ........................................................................195
Szczegy dotyczce obiektw........................................................................................196
Zasady uywania plikw nagwkowych .........................................................................197
Znaczenie plikw nagwkowych.............................................................................198
Problem wielokrotnych deklaracji ............................................................................199
Dyrektywy preprocesora #define, #ifdef i #endif .....................................................200
Standard plikw nagwkowych...............................................................................201
Przestrzenie nazw w plikach nagwkowych ...........................................................202
Wykorzystywanie plikw nagwkowych w projektach ............................................202
Zagniedone struktury ...................................................................................................202
Zasig globalny.........................................................................................................206
Podsumowanie ................................................................................................................206
wiczenia ........................................................................................................................207

Rozdzia 5. Ukrywanie implementacji ............................................................... 211


Okrelanie ogranicze .....................................................................................................211
Kontrola dostpu w C++ .................................................................................................212
Specyfikator protected ..............................................................................................214
Przyjaciele .......................................................................................................................214
Zagniedeni przyjaciele ..........................................................................................216
Czy jest to czyste? .................................................................................................218
Struktura pamici obiektw ............................................................................................219
Klasy................................................................................................................................219
Modyfikacja programu Stash, wykorzystujca kontrol dostpu .............................222
Modyfikacja stosu, wykorzystujca kontrol dostpu ..............................................223
Klasy-uchwyty ................................................................................................................223
Ukrywanie implementacji.........................................................................................224
Ograniczanie powtrnych kompilacji .......................................................................224
Podsumowanie ................................................................................................................226
wiczenia ........................................................................................................................227

Rozdzia 6. Inicjalizacjai kocowe porzdki ...................................................... 229


Konstruktor gwarantuje inicjalizacj ..............................................................................230
Destruktor gwarantuje sprztanie....................................................................................232
Eliminacja bloku definicji ...............................................................................................233
Ptle for.....................................................................................................................235
Przydzielanie pamici ...............................................................................................236
Klasa Stash z konstruktorami i destruktorami.................................................................237
Klasa Stack z konstruktorami i destruktorami ................................................................240
Inicjalizacja agregatowa..................................................................................................242
Konstruktory domylne ...................................................................................................245
Podsumowanie ................................................................................................................246
wiczenia ........................................................................................................................246

Rozdzia 7. Przecianie nazw funkcji i argumenty domylne............................. 249


Dalsze uzupenienia nazw ...............................................................................................250
Przecianie na podstawie zwracanych wartoci......................................................251
czenie bezpieczne dla typw ................................................................................252

Spis treci

9
Przykadowe przecienie ...............................................................................................253
Unie .................................................................................................................................255
Argumenty domylne ......................................................................................................258
Argumenty-wypeniacze ...........................................................................................259
Przecianiekontra argumenty domylne........................................................................260
Podsumowanie ................................................................................................................264
wiczenia ........................................................................................................................265

Rozdzia 8. Stae ............................................................................................. 267


Podstawianie wartoci .....................................................................................................267
Stae w plikach nagwkowych ................................................................................268
Bezpieczestwo staych ............................................................................................269
Agregaty....................................................................................................................270
Rnice w stosunku do jzyka C ..............................................................................271
Wskaniki........................................................................................................................272
Wskaniki do staych ................................................................................................272
Stae wskaniki .........................................................................................................273
Przypisanie a kontrola typw....................................................................................274
Argumenty funkcji i zwracane wartoci..........................................................................275
Przekazywanie staej przez warto..........................................................................275
Zwracanie staej przez warto .................................................................................276
Przekazywanie i zwracanie adresw.........................................................................279
Klasy................................................................................................................................282
Stae w klasach..........................................................................................................282
Stae o wartociach okrelonych podczas kompilacji, zawarte w klasach .................285
Stae obiekty i funkcje skadowe ..............................................................................287
volatile.............................................................................................................................292
Podsumowanie ................................................................................................................293
wiczenia ........................................................................................................................294

Rozdzia 9. Funkcje inline ................................................................................ 297


Puapki preprocesora .......................................................................................................298
Makroinstrukcje a dostp..........................................................................................300
Funkcje inline..................................................................................................................301
Funkcje inline wewntrz klas....................................................................................302
Funkcje udostpniajce.............................................................................................303
Klasy Stash i Stack z funkcjami inline............................................................................308
Funkcje inline a kompilator.............................................................................................311
Ograniczenia .............................................................................................................312
Odwoania do przodu................................................................................................313
Dziaania ukryte w konstruktorach i destruktorach ..................................................313
Walka z baaganem .........................................................................................................314
Dodatkowe cechy preprocesora ......................................................................................315
Sklejanie symboli......................................................................................................316
Udoskonalona kontrola bdw.......................................................................................316
Podsumowanie ................................................................................................................319
wiczenia ........................................................................................................................320

Rozdzia 10. Zarzdzanie nazwami ..................................................................... 323


Statyczne elementy jzyka C...........................................................................................323
Zmienne statyczne znajdujce si wewntrz funkcji ................................................324
Sterowanie czeniem ...............................................................................................328
Inne specyfikatory klas pamici................................................................................330
Przestrzenie nazw............................................................................................................330
Tworzenie przestrzeni nazw .....................................................................................330
Uywanie przestrzeni nazw ......................................................................................332
Wykorzystywanie przestrzeni nazw .........................................................................336

10

Thinking in C++. Edycja polska


Statyczne skadowe w C++ .............................................................................................337
Definiowanie pamicidla statycznych danych skadowych......................................337
Klasy zagniedone i klasy lokalne ..........................................................................341
Statyczne funkcje skadowe......................................................................................342
Zalenoci przy inicjalizacjiobiektw statycznych .........................................................344
Jak mona temu zaradzi? ........................................................................................346
Specyfikacja zmiany sposobu czenia ...........................................................................352
Podsumowanie ................................................................................................................353
wiczenia ........................................................................................................................353

Rozdzia 11. Referencjei konstruktor kopiujcy .................................................. 359


Wskaniki w C++............................................................................................................359
Referencje w C++ ...........................................................................................................360
Wykorzystanie referencji w funkcjach .....................................................................361
Wskazwki dotyczce przekazywania argumentw.................................................363
Konstruktor kopiujcy.....................................................................................................363
Przekazywanie i zwracanie przez warto ................................................................364
Konstrukcja za pomoc konstruktora kopiujcego ...................................................369
Domylny konstruktor kopiujcy..............................................................................374
Moliwoci zastpienia konstruktora kopiujcego ...................................................376
Wskaniki do skadowych...............................................................................................378
Funkcje......................................................................................................................380
Podsumowanie ................................................................................................................382
wiczenia ........................................................................................................................383

Rozdzia 12. Przecianie operatorw ................................................................ 387


Ostrzeenie i wyjanienie................................................................................................387
Skadnia...........................................................................................................................388
Operatory, ktre mona przecia.................................................................................389
Operatory jednoargumentowe...................................................................................390
Operatory dwuargumentowe.....................................................................................393
Argumenty i zwracane wartoci................................................................................402
Nietypowe operatory.................................................................................................405
Operatory, ktrych nie mona przecia.................................................................412
Operatory niebdce skadowymi ...................................................................................413
Podstawowe wskazwki ...........................................................................................414
Przecianie operacji przypisania ...................................................................................415
Zachowanie si operatora = ......................................................................................416
Automatyczna konwersja typw .....................................................................................425
Konwersja za pomoc konstruktora..........................................................................425
Operator konwersji....................................................................................................427
Przykad konwersji typw.........................................................................................429
Puapki automatycznej konwersji typw ..................................................................430
Podsumowanie ................................................................................................................432
wiczenia ........................................................................................................................432

Rozdzia 13. Dynamiczne tworzenie obiektw ..................................................... 437


Tworzenie obiektw........................................................................................................438
Obsuga sterty w jzyku C ........................................................................................439
Operator new.............................................................................................................440
Operator delete..........................................................................................................441
Prosty przykad .........................................................................................................442
Narzut menedera pamici........................................................................................442

Spis treci

11
Zmiany w prezentowanych wczeniej przykadach ........................................................443
Usuwanie wskanika void* jest prawdopodobnie bdem .......................................443
Odpowiedzialno za sprztanie wskanikw ..........................................................445
Klasa Stash przechowujca wskaniki......................................................................445
Operatory new i delete dla tablic.....................................................................................450
Upodabnianie wskanika do tablicy .........................................................................451
Brak pamici ...................................................................................................................451
Przecianie operatorw new i delete .............................................................................452
Przecianie globalnych operatorw new i delete ....................................................453
Przecianie operatorw new i delete w obrbie klasy .................................................455
Przecianie operatorw new i deletew stosunku do tablic......................................458
Wywoania konstruktora...........................................................................................460
Operatory umieszczania new i delete .......................................................................461
Podsumowanie ................................................................................................................463
wiczenia ........................................................................................................................463

Rozdzia 14. Dziedziczeniei kompozycja.............................................................. 467


Skadnia kompozycji .......................................................................................................468
Skadnia dziedziczenia ....................................................................................................469
Lista inicjatorw konstruktora ........................................................................................471
Inicjalizacja obiektw skadowych ...........................................................................471
Typy wbudowane znajdujce si na licie inicjatorw.............................................472
czenie kompozycji i dziedziczenia..............................................................................473
Kolejno wywoywaniakonstruktorw i destruktorw ...........................................474
Ukrywanie nazw..............................................................................................................476
Funkcje, ktre nie s automatycznie dziedziczone .........................................................480
Dziedziczenie a statyczne funkcje skadowe ............................................................483
Wybr midzy kompozycj a dziedziczeniem................................................................484
Tworzenie podtypw ................................................................................................485
Dziedziczenie prywatne ............................................................................................487
Specyfikator protected.....................................................................................................488
Dziedziczenie chronione...........................................................................................489
Przecianie operatorw a dziedziczenie........................................................................490
Wielokrotne dziedziczenie ..............................................................................................491
Programowanie przyrostowe...........................................................................................492
Rzutowanie w gr..........................................................................................................492
Dlaczego rzutowanie w gr? ...............................................................................494
Rzutowanie w gr a konstruktor kopiujcy ............................................................494
Kompozycja czy dziedziczenie (po raz drugi)..........................................................497
Rzutowanie w gr wskanikw i referencji ............................................................498
Kryzys .......................................................................................................................498
Podsumowanie ................................................................................................................498
wiczenia ........................................................................................................................499

Rozdzia 15. Polimorfizmi funkcje wirtualne........................................................ 503


Ewolucja programistw jzyka C++...............................................................................504
Rzutowanie w gr..........................................................................................................504
Problem ...........................................................................................................................506
Wizanie wywoania funkcji.....................................................................................506
Funkcje wirtualne............................................................................................................506
Rozszerzalno..........................................................................................................508
W jaki sposb jzyk C++ realizuje pne wizanie?......................................................510
Przechowywanie informacji o typie..........................................................................511
Obraz funkcji wirtualnych ........................................................................................512

12

Thinking in C++. Edycja polska


Rzut oka pod mask ..................................................................................................514
Instalacja wskanika wirtualnego .............................................................................515
Obiekty s inne .........................................................................................................516
Dlaczego funkcje wirtualne?...........................................................................................517
Abstrakcyjne klasy podstawowe i funkcje czysto wirtualne...........................................518
Czysto wirtualne definicje ........................................................................................522
Dziedziczenie i tablica VTABLE....................................................................................523
Okrajanie obiektw...................................................................................................525
Przecianie i zasanianie................................................................................................527
Zmiana typu zwracanej wartoci ..............................................................................529
Funkcje wirtualne a konstruktory....................................................................................530
Kolejno wywoywania konstruktorw...................................................................531
Wywoywanie funkcji wirtualnychwewntrz konstruktorw...................................532
Destruktory i wirtualne destruktory ................................................................................533
Czysto wirtualne destruktory ....................................................................................535
Wirtualne wywoania w destruktorach .....................................................................537
Tworzenie hierarchii bazujcej na obiekcie..............................................................538
Przecianie operatorw .................................................................................................541
Rzutowanie w d............................................................................................................543
Podsumowanie ................................................................................................................546
wiczenia ........................................................................................................................546

Rozdzia 16. Wprowadzenie do szablonw .......................................................... 551


Kontenery ........................................................................................................................551
Potrzeba istnienia kontenerw ..................................................................................553
Podstawy szablonw .......................................................................................................554
Rozwizanie z wykorzystaniem szablonw..............................................................556
Skadnia szablonw.........................................................................................................558
Definicje funkcji niebdcych funkcjami inline .......................................................559
Klasa IntStack jako szablon ......................................................................................560
Stae w szablonach....................................................................................................562
Klasy Stack i Stash jako szablony...................................................................................563
Kontener wskanikw Stash,wykorzystujcy szablony ...........................................565
Przydzielanie i odbieranieprawa wasnoci.....................................................................570
Przechowywanie obiektwjako wartoci ........................................................................573
Wprowadzenie do iteratorw ..........................................................................................575
Klasa Stack z iteratorami ..........................................................................................582
Klasa PStash z iteratorami ........................................................................................585
Dlaczego iteratory? .........................................................................................................590
Szablony funkcji .......................................................................................................593
Podsumowanie ................................................................................................................594
wiczenia ........................................................................................................................594

Dodatek A Styl kodowania .............................................................................. 599


Dodatek B Wskazwki dla programistw ......................................................... 609
Dodatek C Zalecana literatura ........................................................................ 621
Jzyk C ............................................................................................................................621
Oglnie o jzyku C++ .....................................................................................................621
Ksiki, ktre napisaem...........................................................................................622
Gbia i mroczne zauki...................................................................................................623
Analiza i projektowanie ..................................................................................................623

Skorowidz...................................................................................... 627

Rozdzia 5.

Ukrywanie implementacji
Typowa biblioteka skada si w jzyku C ze struktury i kilku doczonych funkcji,
wykonujcych na niej operacje. Zapoznalimy si ze sposobem, w jaki jzyk C++
grupuje funkcje, zwizane ze sob pojciowo, i czy je literalnie. Dokonuje tego
umieszczajc deklaracje funkcji w obrbie zasigu struktury, zmieniajc sposb,
w jaki funkcje te s wywoywane w stosunku do tej struktury, eliminujc przekazywanie adresu struktury jako pierwszego argumentu i dodajc do programu nazw nowego typu (dziki czemu nie trzeba uywa sowa kluczowego typedef w stosunku
do identyfikatora struktury).
Wszystko to zapewnia wiksz wygod pozwala lepiej zorganizowa kod i uatwia
zarwno jego napisanie, jak i przeczytanie. Warto jednak poruszy jeszcze inne wane
zagadnienia, zwizane z atwiejszym tworzeniem bibliotek w jzyku C++ w szczeglnoci s to kwestie, dotyczce bezpieczestwa i kontroli. W niniejszym rozdziale zapoznamy si bliej z kwestiami ogranicze dotyczcych struktur.

Okrelanie ogranicze
W kadej relacji istotne jest okrelenie granic, respektowanych przez wszystkie zaangaowane w ni strony. Tworzc bibliotek, ustanawiasz relacj z klientem-programist,
uywajcym twojej biblioteki do zbudowania aplikacji lub utworzenia innej biblioteki.
W strukturach dostpnych w jzyku C, podobnie jak w wikszoci elementw tego
jzyka, nie obowizuj adne reguy. Klienci-programici mog postpi dowolnie ze
struktur i nie ma adnego sposobu, by wymusi na nich jakiekolwiek szczeglne zachowania. Na przykad mimo wanoci funkcji o nazwach initialize( ) i cleanup( )
(wskazanej w poprzednim rozdziale), klient-programista moe w ogle ich nie wywoa (lepsze rozwizanie tej kwestii zaprezentujemy w nastpnym rozdziale). W jzyku C nie ma adnego sposobu zapobieenia temu, by klienci-programici operowali
bezporednio na niektrych skadowych struktur. Wszystko ma charakter jawny.

212

Thinking in C++. Edycja polska

Istniej dwa powody wprowadzenia kontroli dostpu do skadowych struktur. Przede


wszystkim programistom naley uniemoliwi stosowanie narzdzi niezbdnych do
wykonywania wewntrznych operacji zwizanych z typem danych, lecz niebdcych
czci interfejsu potrzebnego klientom-programistom do rozwizania ich wasnych
problemw. Jest to w rzeczywistoci pomoc udzielana klientom-programistom, poniewa dziki temu mog atwo odrni kwestie istotne od pozostaych.
Drugim powodem wprowadzenia kontroli dostpu jest umoliwienie projektantowi
biblioteki zmiany wewntrznych mechanizmw struktury z pominiciem wpywu na
klienta-programist. W przykadzie ze stosem, przedstawionym w poprzednim rozdziale, z uwagi na szybko mona by przydziela pami duymi porcjami zamiast
tworzy kolejny jej obszar, ilekro dodawany jest nowy element. Jeeli interfejs oraz
implementacja s wyranie od siebie oddzielone i chronione, mona tego dokona,
wymagajc od klienta-programisty jedynie przeprowadzenia ponownego czenia
moduw wynikowych.

Kontrola dostpu w C++


Jzyk C++ wprowadza trzy nowe sowa kluczowe, pozwalajce na okrelenie granic
w obrbie struktur: public (publiczny), private (prywatny) i protected (chroniony).
Sposb ich uycia oraz znaczenie wydaj si do oczywiste. S one specyfikatorami
dostpu (ang. access specifiers), uywanymi wycznie w deklaracjach struktur,
zmieniajcymi ograniczenia dla wszystkich nastpujcych po nich definicji. Specyfikator dostpu zawsze musi koczy si rednikiem.
Specyfikator public oznacza, e wszystkie nastpujce po nim deklaracje skadowych
s dostpne dla wszystkich. Skadowe publiczne s takie same, jak zwyke skadowe
struktur. Na przykad ponisze deklaracje struktur s identyczne:


  
 

  !
  "
 #"

"
$ % &'"
("
$ %  &'!(
 )!


  "
 #"

"
$ % &'"
("

Rozdzia 5. Ukrywanie implementacji

213

$ %) &'!(
 &'!
 ") "
 * *+"
 * *, ,"
 * *- +.+/"
  &'"
  &'"
(0

Z kolei sowo kluczowe private oznacza, e do skadowych struktury nie ma dostpu


nikt, oprcz ciebie, twrcy typu, i to jedynie w obrbie funkcji skadowych tego typu.
Specyfikator private stanowi barier pomidzy tob i klientem-programist kady,
kto sprbuje odwoa si do prywatnej skadowej klasy, otrzyma komunikat o bdzie
ju na etapie kompilacji. W powyszej strukturze B mgby chcie na przykad
ukry cz jej reprezentacji (tj. danych skadowych), dziki czemu byyby one dostpne wycznie dla ciebie:
 $ 
12
 3 
 )!
 $
 #"

"


  "
$ % &'"
("
$ %) &'!
 *"
*,,"
* "
("
 &'!
) "
 *+"145%

6 *,+,"7 %
5%
6 *+ "7 %
5%
(0

Mimo e funkcja func( ) ma dostp do kadej skadowej struktury B (poniewa jest


ona rwnie skadow struktury B, wic automatycznie uzyskuje do tego prawo), to
zwyka funkcja globalna, taka jak main( ), nie posiada takich uprawnie. Oczywicie,
do tych skadowych nie maj dostpu rwnie funkcje skadowe innych struktur.
Wycznie funkcje, ktre zostay wyranie wymienione w deklaracji struktury (kontrakt), maj dostp do prywatnych skadowych struktury.
Nie istnieje okrelony porzdek, w jakim powinny wystpowa specyfikatory dostpu;
mog one rwnie wystpowa wicej ni jednokrotnie. Dotycz one wszystkich zadeklarowanych po nich skadowych, a do napotkania nastpnego specyfikatora dostpu.

214

Thinking in C++. Edycja polska

Specyfikator protected
Ostatnim specyfikatorem dostpu jest protected. Jego znaczenie jest zblione do specyfikatora private, z jednym wyjtkiem, ktry nie moe zosta jeszcze teraz wyjaniony struktury dziedziczce (ktre nie posiadaj dostpu do skadowych prywatnych) maj zagwarantowany dostp do skadowych oznaczonych specyfikatorem
protected. Zostanie to wyjanione w rozdziale 14., przy okazji wprowadzenia pojcia
dziedziczenia. Tymczasowo mona przyj, e specyfikator protected dziaa podobnie do specyfikatora private.

Przyjaciele
Co zrobi w sytuacji, gdy chcemy jawnie udzieli pozwolenia na dostp funkcji, niebdcej skadow biecej struktury? Uzyskuje si to, deklarujc funkcj za pomoc sowa
kluczowego friend (przyjaciel) wewntrz deklaracji struktury. Wane jest, by deklaracja
friend wystpowaa w obrbie deklaracji struktury, poniewa programista (i kompilator),
czytajc deklaracj struktury, musi pozna wszystkie zasady dotyczce wielkoci i zachowania tego typu danych. A niezwykle wan zasad, obowizujc w kadej relacji,
stanowi odpowied na pytanie: Kto ma dostp do mojej prywatnej implementacji?.
To sama struktura okrela, ktry kod ma dostp do jej skadowych. Nie ma adnego magicznego sposobu wamania si z zewntrz, jeeli nie jest si przyjacielem nie
mona zadeklarowa nowej klasy, twierdzc: Cze, jestem przyjacielem Boba! i spodziewajc si, e zapewni to dostp do prywatnych i chronionych skadowych klasy Bob.
Wolno zadeklarowa jako przyjaciela funkcj globaln; moe nim by rwnie
skadowa innej struktury albo nawet caa struktura zadeklarowana z uyciem sowa
kluczowego friend. Poniej zamieszczono przykad:
8 % 

  %% 

%
9
 & 
   '
 :"
 ;!
$ %&:<'"
("
 :!9  
 $
  "


$ %   
&'"
 %$ %3&:<5 '" 
3
 

 %$ %;&:<'" 
 %= %=
 % >" 

 %$ %#&'"


("

Rozdzia 5. Ukrywanie implementacji

215

$ %:   
&'!
 *"
(
$ %3&:<?5  '!
?@A * "
(
$ %;&:<?'!
?@A *.B"
(
 >!
 $
 "


$ %   
&'"
$ %3&:<?'"
("
$ %>   
&'!
*//"
(
$ %>3&:<?'!
?@A C*"
(
$ %#&'!
:?"
? *+")2%  %
(
 &'!
:?"
>"
 3&D?'"
(0

Struktura Y posiada funkcj skadow f( ), modyfikujc obiekt typu X. Jest to nieco


zagadkowe, poniewa kompilator jzyka C++ wymaga zadeklarowania kadej rzeczy
przed odwoaniem si do niej. Naley wic zadeklarowa struktur Y, zanim jeszcze
jej skadowa Y::f(X*) bdzie moga zosta zadeklarowana jako przyjaciel struktury
X. Jednake, aby funkcja Y::f(X*) moga zosta zadeklarowana, najpierw naley zadeklarowa struktur X!
Oto rozwizanie. Zwr uwag na to, e funkcja Y::f(X*) pobiera adres obiektu X.
Jest to istotne, poniewa kompilator zawsze wie, w jaki sposb przekaza adres bdcy staej wielkoci, niezalenie od przekazywanego za jego porednictwem obiektu
i nawet jeeli nie posiada penej informacji dotyczcej jego wielkoci. Jednake
w przypadku prby przekazania caego obiektu kompilator musi widzie ca definicj struktury X, aby pozna jej wielko i wiedzie, w jaki sposb j przekaza, zanim
pozwoli na deklaracj funkcji w rodzaju Y::g(X).

216

Thinking in C++. Edycja polska

Przekazujc adres struktury X, kompilator pozwala na utworzenie niepenej specyfikacji typu X, umieszczonej przed deklaracj Y::f(X*). Uzyskuje si j za pomoc deklaracji:
 :"

Deklaracja ta informuje kompilator, e istnieje struktura o podanej nazwie, wic mona odwoa si do niej, dopki nie jest na jej temat potrzebna adna dodatkowa wiedza, poza nazw.
Potem funkcja Y::f(X*) w strukturze X moe by ju bez problemu zadeklarowana
jako przyjaciel. W razie prby zadeklarowania jej, zanim kompilator napotka pen
specyfikacj klasy Y, nastpioby zgoszenie bdu. Jest to cecha zapewniajca bezpieczestwo i spjno, a take zapobiegajca bdom.
Zwr uwag na dwie pozostae funkcje zadeklarowane z uyciem sowa kluczowego
friend. Pierwsza z nich deklaruje jako przyjaciela zwyk funkcj globaln g( ).
Funkcja ta nie zostaa jednak wczeniej zadeklarowana w zasigu globalnym! Okazuje si, e taki sposb uycia deklaracji friend moe zosta wykorzystany do rwnoczesnego zadeklarowania funkcji i nadania jej statusu przyjaciela. Dotyczy to rwnie caych struktur. Deklaracja:
 % >"

jest niepen specyfikacj typu struktury Z, nadajc rwnoczenie caej tej strukturze
status przyjaciela.

Zagniedeni przyjaciele
Utworzenie struktury zagniedonej nie zapewnia jej automatycznie prawa dostpu
do skadowych prywatnych. Aby to osign, naley postpi w szczeglny sposb:
najpierw zadeklarowa (nie definiujc) struktur zagniedon, nastpnie zadeklarowa j, uywajc sowa kluczowego friend, a na koniec zdefiniowa struktur.
Definicja struktury musi by oddzielona od deklaracji friend, bo w przeciwnym
przypadku kompilator nie uznaby jej za skadow struktury. Poniej zamieszczono
przykad takiego zagniedenia struktury:
78 % 
>3 E%E F 
F
G 
%H A
G 
%H  3A&'
 3 %"
 *I"
 J
%!
 $
 KL"


$ %   
&'"
  "
 % "
  !

Rozdzia 5. Ukrywanie implementacji


 $
J
%<#"
 <"


$ %   
&J
%<#'"
    

$ %?&'"
$ %$ &'"
$ %&'"
$ %%&'"
9%2 
 %&'"
$ %&  '"
("
("
$ %J
%   
&'!
&55< & ''"
(
$ %J
%    
&J
%<$'!
#*$"
*$@A"
(
$ %J
% ?&'!
 &HD&#@AK@+L''CC"
(
$ %J
% $ &'!
 &AD&#@AKL''@@"
(
$ %J
% &'!
*D&#@AKL'"
(
$ %J
% %&'!
*D&#@AK@+L'"
(
J
% %&'!
<"
(
$ %J
% &  '!
<* "
(
 &'!
J
%#"
J
% #5#I"
  "
#   
&'"
#   
&D#'"
#I   
&D#'"

217

218

Thinking in C++. Edycja polska


& *" H" CC'!
# & '"
# ?&'"
(
# &'"
#I %&'"
& *" H" CC'!
 HHF#*FHH# %&'
HHF5#I*FHH#I %&'HH%
"
# ?&'"
#I $ &'"
(
(0

Po zadeklarowaniu struktury Pointer deklaracja:


 % "

zapewnia jej dostp do prywatnych skadowych struktury Holder. Struktura Holder


zawiera tablic liczb cakowitych, do ktrych dostp jest moliwy wanie dziki strukturze Pointer. Poniewa struktura Pointer jest cile zwizana ze struktur Holder, rozsdne jest uczynienie z niej skadowej struktury Holder. Poniewa jednak Pointer stanowi oddzieln struktur w stosunku do struktury Holder, mona utworzy w funkcji
main( ) wiksz liczb jej egzemplarzy, uywajc ich nastpnie do wyboru rnych
fragmentw tablicy. Pointer jest struktur z niezwykym wskanikiem jzyka C, gwarantuje wic zawsze poprawne wskazania w obrbie struktury Holder.
Funkcja memset( ), wchodzca w skad standardowej biblioteki jzyka C (zadeklarowana w <cstring>), zostaa dla wygody wykorzystana w powyszym programie. Poczwszy od okrelonego adresu (bdcego pierwszym argumentem) wypenia ona
ca pami odpowiedni wartoci (podan jako drugi argument), wypeniajc n kolejnych bajtw (n stanowi trzeci argument). Oczywicie, mona przej przez kolejne
adresy pamici, uywajc do tego ptli, ale funkcja memset( ) jest dostpna, starannie
przetestowana (wic jest mao prawdopodobne, e powoduje bdy) i prawdopodobnie bardziej efektywna ni kod napisany samodzielnie.

Czy jest to czyste?


Definicja klasy udostpnia dziennik nadzoru, dziki ktremu analizujc klas mona okreli funkcje majce prawo do modyfikacji jej prywatnych elementw. Jeeli
funkcja zostaa zadeklarowana z uyciem sowa kluczowego friend, oznacza to, e
nie jest ona funkcj skadow, ale mimo to chcemy da jej prawo do modyfikacji
prywatnych danych. Musi ona widnie w definicji klasy, by wszyscy wiedzieli, e
naley do funkcji uprzywilejowanych w taki wanie sposb.
Jzyk C++ jest hybrydowym jzykiem obiektowym, a nie jzykiem czysto obiektowym. Sowo kluczowe friend zostao do niego dodane w celu pominicia problemw,
ktre zdarzaj si w praktyce. Mona sformuowa zarzut, e czyni to jzyk mniej
czystym. C++ zosta bowiem zaprojektowany w celu sprostania wymogowi uytecznoci, a nie po to, by aspirowa do miana abstrakcyjnego ideau.

Rozdzia 5. Ukrywanie implementacji

219

Struktura pamici obiektw


W rozdziale 4. napisano, e struktura przygotowana dla kompilatora jzyka C, a nastpnie skompilowana za pomoc kompilatora C++, nie powinna ulec zmianie. Odnosi si to przede wszystkim do ukadu pamici obiektw tej struktury, to znaczy okrelenia, jak w pamici przydzielonej obiektowi rozmieszczone s poszczeglne
zmienne, stanowice jego skadowe. Gdyby kompilator jzyka C++ zmienia ukad
pamici struktur jzyka C, to nie dziaaby aden program napisany w C, ktry (co nie
jest zalecane) wykorzystywaby informacj o rozmieszczeniu w pamici zmiennych
tworzcych struktur.
Rozpoczcie stosowania specyfikatorw dostpu zmienia jednak nieco posta rzeczy,
przenoszc nas cakowicie w domen jzyka C++. W obrbie okrelonego bloku dostpu (grupy deklaracji, ograniczonej specyfikatorami dostpu), gwarantowany jest
zwarty ukad zmiennych w pamici, tak jak w jzyku C. Jednake poszczeglne bloki
dostpu mog nie wystpowa w obiekcie w kolejnoci, w ktrej zostay zadeklarowane. Mimo e kompilator zazwyczaj umieszcza te bloki w pamici dokadnie w takiej kolejnoci, w jakiej s one widoczne w programie, nie obowizuje w tej kwestii
adna regua. Niektre architektury komputerw i (lub) rodowiska systemw operacyjnych mog bowiem udziela jawnego wsparcia skadowym prywatnym i chronionym, co moe z kolei wymaga umieszczenia tych blokw w specjalnych obszarach
pamici. Specyfikacja jzyka nie ma na celu ograniczenie moliwoci wykorzystania
tego typu korzyci.
Specyfikatory dostpu stanowi skadniki struktur i nie wpywaj na tworzone na ich
podstawie obiekty. Wszelkie informacje dotyczce specyfikacji dostpu znikaj, zanim jeszcze program zostanie uruchomiony na og dzieje si to w czasie kompilacji. W dziaajcym programie obiekty staj si obszarami pamici i niczym wicej.
Jeeli naprawd tego chcesz, moesz zama wszelkie reguy, odwoujc si bezporednio do pamici, tak jak w jzyku C. Jzyka C++ nie zaprojektowano po to, by chroni
ci przed popenianiem gupstw. Stanowi on jedynie znacznie atwiejsze i bardziej
wartociowe rozwizanie alternatywne.
Na og poleganie podczas pisania programu na czymkolwiek, co jest zalene od implementacji, nie jest dobrym pomysem. Jeeli musisz uy czego, co zaley od implementacji, zamknij to w obrbie struktury, dziki czemu zmiany zwizane z przenoszeniem programu bd skupione w jednym miejscu.

Klasy
Kontrola dostpu jest czsto okrelana mianem ukrywania implementacji. Umieszczenie funkcji w strukturach (czsto nazywane kapsukowaniem1) tworzy typy danych, posiadajce zarwno cechy, jak i zachowanie. Jednake kontrola dostpu wy1

Jak ju wspomniano, kapsukowaniem jest rwnie czsto nazywana kontrola dostpu.

220

Thinking in C++. Edycja polska

znacza ograniczenia w obrbie tych typw danych, wynikajce z dwch istotnych


powodw. Po pierwsze, okrelaj one, co moe, a czego nie moe uywa klientprogramista. Mona wbudowa w struktur wewntrzne mechanizmy, nie martwic
si o to, e klienci-programici uznaj te mechanizmy za cz interfejsu, ktrego
powinni uywa.
Prowadzi to bezporednio do drugiego z powodw, ktrym jest oddzielenie interfejsu
od implementacji. Jeeli struktura jest uywana w wielu programach, lecz klienciprogramici mog jedynie wysya komunikaty do jej publicznego interfejsu, to mona w niej zmieni wszystko co jest prywatne, bez potrzeby zmiany kodu wykorzystujcych j programw.
Kapsukowanie i kontrola dostpu, traktowane cznie, tworz co wicej ni struktury dostpne w jzyku C. Dziki nim wkraczamy do wiata programowania obiektowego, w ktrym struktury opisuj klasy obiektw w taki sposb, jakbymy opisywali
klas ryb albo klas ptakw kady obiekt, nalecy do tych klas, bdzie posiada
takie same cechy oraz rodzaje zachowa. Tym wanie staa si deklaracja struktury
opisem, w jaki sposb wygldaj i funkcjonuj wszystkie obiekty jej typu.
W pierwszym jzyku obiektowym, Simuli-67, sowo kluczowe class suyo do opisu
nowych typw danych. Najwyraniej zainspirowao to Stroustrupa do wyboru tego
samego sowa kluczowego dla jzyka C++. wiadczy to o tym, e najwaniejsz cech caego jzyka jest tworzenie nowych typw danych, bdce czym wicej ni
strukturami jzyka C zaopatrzonymi w funkcje. Z pewnoci wydaje si to wystarczajcym uzasadnieniem wprowadzenia nowego sowa kluczowego.
Jednake sposb uycia sowa kluczowego class w jzyku C++ powoduje, e jest ono
niemal niepotrzebne. Jest identyczne ze sowem kluczowym struct pod kadym
wzgldem, z wyjtkiem jednego: skadowe klasy s domylnie prywatne, a skadowe
struktury domylnie publiczne. Poniej przedstawiono dwie struktury, dajce takie
same rezultaty:

 
% M 

  !
 $
  55"


 &'"
$ %3&'"
("
 &'!
 CC"
(
$ % 3&'!
 ***"
(
N 
  =

Rozdzia 5. Ukrywanie implementacji

221


)!
  55"


 &'"
$ %3&'"
("
)&'!
 CC"
(
$ %)3&'!
 ***"
(
 &'!
 "
) "
 &'" 3&'"
 &'" 3&'"
(0

Klasa jest w jzyku C++ podstawowym pojciem zwizanym z programowaniem


obiektowym. Jest jednym ze sw kluczowych, ktre nie zostay zaznaczone w ksice pogrubion czcionk byoby to irytujce w przypadku sowa powtarzanego tak
czsto jak class. Przejcie do klas jest tak istotnym krokiem, e podejrzewam, i
Stroustrup miaby ochot wyrzuci w ogle sowo kluczowe struct. Przeszkod stanowi jednak konieczno zachowania wstecznej zgodnoci jzyka C++ z jzykiem C.
Wiele osb preferuje styl tworzenia klas bliszy strukturom ni klasom. Nie przywizuj one wagi do domylnie prywatnego zachowania klas, rozpoczynajc deklaracje
klas od ich elementw publicznych:

:!


$ % O &'"
 $
$ % O&'"
 O "
("

Przemawia za tym argument, e czytelnikowi takiego kodu wydaje si bardziej logiczne czytanie najpierw interesujcych go skadowych, a nastpnie pominicie
wszystkiego, co zostao oznaczone jako prywatne. Faktycznie, wszystkie pozostae
skadowe naley zadeklarowa w obrbie klasy jedynie dlatego, e kompilator musi
zna wielkoci obiektw, by mg przydzieli im we waciwy sposb pami. Istotna
jest take moliwo zagwarantowania spjnoci klasy.
Jednak w przykadach wystpujcych w ksice skadowe prywatne bd znajdoway
si na pocztku deklaracji klasy, jak poniej:

:!
$ % O&'"
 O "


$ % O &'"
("

222

Thinking in C++. Edycja polska

Niektrzy zadaj sobie nawet trud uzupeniania swoich prywatnych nazw:



;!


$ %&'"
 $
 :"P 
("

Poniewa zmienna mX jest ju ukryta w zasigu klasy Y, przedrostek m (od ang.


member czonek, skadowa) jest niepotrzebny. Jednak w projektach o wielu
zmiennych globalnych (czego naley unika, ale co w przypadku istniejcych projektw jest czasami nieuniknione) wan rol odgrywa moliwo odrnienia, ktre
dane s danymi globalnymi, a ktre skadowymi klasy.

Modyfikacja programu Stash,


wykorzystujca kontrol dostpu
Modyfikacja programu z rozdziau 4., dokonana w taki sposb, by uywa on klas
oraz kontroli dostpu, wydaje si racjonalna. Zwr uwag na to, w jaki sposb cz
interfejsu, przeznaczona dla klienta-programisty, zostaa obecnie wyranie wyrniona. Dziki temu nie istnieje ju moliwo, e przypadkowo bdzie on wykonywa
operacje na nieodpowiedniej czci klasy:
# #
>   
 
%
G %N JOJ
G% N JOJ

#!
  "Q 
2RE%3

 S "T  
U 
 ?"7

9  % 

 U
 3% #<3"
$ % 
&   '"


$ %   
&  '"
$ %
&'"
 %%&$ %<
'"
$ %< #&  %?'"
  &'"
("
G% N JOJ0

Funkcja inflate( ) zostaa okrelona jako prywatna, poniewa jest ona uywana wycznie przez funkcj add( ); stanowi zatem cz wewntrznego mechanizmu funkcjonowania klasy, a nie jej interfejsu. Oznacza to, e w przyszoci mona bdzie
zmieni wewntrzn implementacj, uywajc innego systemu zarzdzania pamici.
Powysza zawarto pliku nagwkowego jako jedyna poza jego nazw ulega
modyfikacji w powyszym przykadzie. Zarwno plik zawierajcy implementacj, jak
i plik testowy pozostay takie same.

Rozdzia 5. Ukrywanie implementacji

223

Modyfikacja stosu, wykorzystujca kontrol dostpu


W drugim przykadzie w klas zostanie przeksztacony program tworzcy stos. Zagniedona struktura danych jest obecnie struktur prywatn, co wydaje si korzystne, poniewa gwarantuje, e klient-programista nigdy nie bdzie musia si jej przyglda ani nie uzaleni on swojego programu od wewntrznej reprezentacji klasy
Stack:
 I #
>3 E%E5= 
 ==
G %N 4IOJ
G% N 4IOJ

 !
 T !
$ %<%"
T <?"
$ %   
&$ %<%5T <?'"
(<#%"


$ %   
&'"
$ %#&$ %<%'"
$ %<&'"
$ %<&'"
$ %
&'"
("
G% N 4IOJ0

Podobnie jak poprzednio, implementacja nie ulega w tym przypadku zmianie, nie zostaa wic w tym miejscu powtrnie przytoczona. Plik zawierajcy program testowy
rwnie si nie zmieni. Zostaa jedynie zmodyfikowana moc, uzyskana dziki interfejsowi klasy. Istotn korzyci, wynikajc z kontroli dostpu, jest uniemoliwienie
przekraczania granic podczas tworzenia programu. W rzeczywistoci jedynie kompilator posiada informacje dotyczce poziomu zabezpiecze poszczeglnych skadowych klasy. Nie istnieje adna informacja umoliwiajca kontrol dostpu, ktra byaby doczana do nazwy skadowej klasy, a nastpnie przekazywana programowi
czcemu. Caa kontrola zabezpiecze jest dokonywana przez kompilator i nie zostaje przerwana w czasie wykonywania programu.
Zwr uwag na to, e interfejs prezentowany klientowi-programicie rzeczywicie
odpowiada teraz rozwijanemu w d stosowi. Jest on obecnie zaimplementowany
w postaci powizanej listy, lecz mona to zmieni, nie modyfikujc elementw wykorzystywanych przez klienta-programist, a zatem (co waniejsze) rwnie ani jednego
wiersza napisanego przez niego kodu.

Klasy-uchwyty
Kontrola dostpu w jzyku C++ pozwala na oddzielenie interfejsu od implementacji, jednak ukrycie implementacji jest tylko czciowe. Kompilator musi nadal widzie deklaracje wszystkich elementw obiektu po to, by mg poprawnie je tworzy i odpowiednio

224

Thinking in C++. Edycja polska

obsugiwa. Mona wyobrazi sobie jzyk programowania, ktry wymagaby okrelenia jedynie publicznego interfejsu obiektu, pozwalajc na ukrycie jego prywatnej
implementacji. Jednake jzyk C++ dokonuje kontroli typw statycznie (w czasie
kompilacji), zawsze gdy jest to tylko moliwe. Oznacza to, e programista jest powiadamiany o bdach moliwie jak najszybciej, a take to, e program jest bardziej
efektywny. Jednak doczenie prywatnej implementacji pociga za sob dwa skutki
implementacja jest widoczna, nawet jeeli nie ma do niej atwego dostpu, a ponadto moe ona wywoywa niepotrzebnie powtrn kompilacj programu.

Ukrywanie implementacji
W przypadku niektrych projektw nie wolno dopuci do tego, by ich implementacja
bya widoczna dla klienta-programisty. Plik nagwkowy biblioteki moe zawiera informacje o znaczeniu strategicznym, ktrych firma nie zamierza udostpnia konkurentom.
By moe pracujesz nad systemem, w ktrym istotn kwesti stanowi bezpieczestwo
na przykad algorytm szyfrowania i nie chcesz umieszcza w pliku nagwkowym
informacji, ktre mogyby uatwi zamanie kodu. Albo zamierzasz umieci swoj bibliotek we wrogim rodowisku, w ktrym programici i tak bd odwoywa si do
prywatnych skadowych klasy wykorzystujc wskaniki i rzutowanie. We wszystkich
takich przypadkach lepiej skompilowa rzeczywist struktur klasy wewntrz pliku, zawierajcego jej implementacj, ni ujawnia j w pliku nagwkowym.

Ograniczanie powtrnych kompilacji


Meneder projektu, dostpny w uywanym przez ciebie rodowisku programistycznym, spowoduje powtrn kompilacj kadego pliku, jeli zosta on zmodyfikowany,
lub jeeli zosta zmieniony plik, od ktrego jest on zaleny czyli doczony do niego plik nagwkowy. Oznacza to, e ilekro dokonywana jest zmiana dotyczca klasy
(niezalenie od tego, czy dotyczy ona deklaracji jej publicznego interfejsu, czy te
skadowych prywatnych), jeste zmuszony do powtrnej kompilacji wszystkich plikw, do ktrych doczony jest plik nagwkowy tej klasy. Czsto jest to okrelane
mianem problemu wraliwej klasy podstawowej. W przypadku wczesnych etapw realizacji duych projektw moe to by irytujce, poniewa wewntrzna implementacja podlega czstym zmianom gdy projekt taki jest bardzo obszerny, czas potrzebny na kompilacje niekiedy uniemoliwia szybkie wprowadzanie w nim zmian.
Technika rozwizujca ten problem nazywana jest czasami klasami-uchwytami (ang.
handle classes) lub kotem z Cheshire2 wszystko, co dotyczy implementacji znika i pozostaje tylko pojedynczy wskanik umiech. Wskanik odnosi si do
struktury, ktrej definicja znajduje si w pliku zawierajcym implementacj, wraz
z wszystkimi definicjami funkcji skadowych. Tak wic dopki nie zmieni si interfejs, dopty plik nagwkowy pozostaje niezmieniony. Implementacja moe by dowolnie zmieniana w kadej chwili, powodujc jedynie konieczno ponownej kompilacji i powtrnego poczenia z projektem pliku zawierajcego implementacj.
2

Nazwa ta jest przypisywana Johnowi Carolanowi, jednemu z pionierw programowania w C++


i, oczywicie, Lewisowi Carollowi. Mona j rwnie postrzega jako form pomostowego
wzorca projektowego, opisanego w drugim tomie ksiki.

Rozdzia 5. Ukrywanie implementacji

225

Poniej zamieszczono prosty przykad, demonstrujcy wykorzystanie tej techniki.


Plik nagwkowy zawiera wycznie publiczny interfejs klasy oraz wskanik do (nie
w peni okrelonej) klasy:
J%
 #
4
@ #
G %J 79TVOJ
G% J 79TVOJ

J%
!
 ## "N
%
 

## <
"


$ %   
&'"
$ %
&'"
 %&'"
$ % #3& '"
("
G% J 79TVOJ0

To wszystko, co widzi klient-programista. Wiersz:


 ## "

stanowi niepen specyfikacj typu albo deklaracj klasy (definicja klasy zawieraaby
jej ciao). Informuje ona kompilator, e Cheshire jest nazw struktury, lecz nie dostarcza adnych szczegw na jej temat. Informacja wystarcza jedynie do utworzenia
wskanika do tej struktury nie mona utworzy obiektu, dopki nie zostanie udostpnione jej ciao. W przypadku zastosowania tej techniki ciao to jest ukryte w pliku
zawierajcym implementacj:
J%
 !1(
W
  #
G 
%FJ%
 #F
G 
%F S  #F
9   
   #
 J%
## !
  "
("
$ %J%
   
&'!

*## "

@A *"
(
$ %J%

&'!
%

"
(
J%
%&'!

@A "
(
$ %J%
 #3& ?'!

@A *?"
(0

226

Thinking in C++. Edycja polska

Cheshire jest struktur zagniedon, musi wic ona zosta zdefiniowana w zasigu
klasy:
 J%
## !

W funkcji Handle::initialize( ) strukturze Cheshire przydzielana jest pami, ktra


jest pniej zwalniana przez funkcj Handle::cleanup( ). Pami ta jest uywana
zamiast wszystkich elementw danych, ktre s zazwyczaj umieszczane w prywatnej
czci klasy. Po skompilowaniu pliku Handle.cpp definicja tej struktury zostaje
ukryta w pliku wynikowym i nie jest ona dla nikogo widoczna. Jeeli nastpuje zmiana elementw struktury Ceshire, to jedynym plikiem, ktry musi zosta powtrnie
skompilowany, jest Handle.cpp, poniewa plik nagwkowy pozostanie niezmieniony.
Sposb uycia klasy Handle przypomina wykorzystywanie kadej innej klasy naley doczy jej plik nagwkowy, utworzy obiekty i wysya do nich komunikaty:
PJ%
 
!T(J%

PE 
@ #
G 
%FJ%
 #F
 &'!
J%
"
   
&'"
 %&'"
 #3&+'"

&'"
(0

Jedyn rzecz, do ktrej ma dostp klient, jest publiczny interfejs klasy. Dopki wic
zmienia si jedynie jej implementacja, powyszy plik nie bdzie nigdy wymaga powtrnej kompilacji. Tak wic, mimo e nie jest to doskonay sposb ukrycia implementacji, stanowi on w tej dziedzinie ogromny krok naprzd.

Podsumowanie
Kontrola dostpu w jzyku C++ zapewnia programicie cisy nadzr nad utworzon
przez siebie klas. Uytkownicy klasy widz w przejrzysty sposb, czego mog uywa, a co powinni zignorowa. Jeszcze waniejsza jest moliwo gwarancji, e aden klient-programista nie bdzie uzaleniony od jakiejkolwiek czci kodu tworzcego wewntrzn implementacj klasy. Dziki temu twrca klasy moe zmieni
wewntrzn implementacj, wiedzc e aden z klientw-programistw nie zostanie
zmuszony do wprowadzania jakichkolwiek modyfikacji w swoim programie, poniewa nie ma on dostpu do tej czci klasy.
Majc moliwo zmiany wewntrznej implementacji, mona nie tylko udoskonali
swj projekt, ale rwnie pozwoli sobie na popenianie bdw. Bez wzgldu na to,
jak skrupulatnie zaplanuje si wszystko i wykona, i tak dojdzie do pomyek. Wiedza,
e popenianie takich bdw jest stosunkowo bezpieczne, umoliwia eksperymentowanie, efektywniejsz nauk i szybsze zakoczenie projektu.

Rozdzia 5. Ukrywanie implementacji

227

Publiczny interfejs klasy jest tym, co widzi klient-programista, naley wic we waciwy sposb przemyle go w trakcie analizy i projektowania. Lecz nawet on pozostawia pewn moliwo wprowadzania zmian. Jeeli posta interfejsu nie zostanie
od razu gruntownie przemylana, mona uzupeni go o nowe funkcje, pod warunkiem, e nie zostan z niego usunite te spord funkcji, ktre zostay ju uyte przez
klientw-programistw.

wiczenia
Rozwizania wybranych wicze znajduj si w dokumencie elektronicznym: The
Thinking in C++ Annotated Solution Guide, ktry mona pobra za niewielk opat
z witryny http://www.BruceEckel.com.
1. Utwrz klas posiadajc dane skadowe publiczne, prywatne oraz chronione.

Utwrz obiekt tej klasy i zobacz, jakie komunikaty kompilatora uzyskasz,


prbujc odwoa si do wszystkich danych skadowych klasy.
2. Utwrz struktur o nazwie Lib, zawierajc trzy obiekty bdce acuchami

(string): a, b oraz c. W funkcji main( ) utwrz obiekt o nazwie x i przypisz


wartoci skadowym x.a, x.b oraz x.c. Wydrukuj te wartoci. Nastpnie zastp
skadowe a, b i c tablic, zdefiniowan jako string s[3]. Zauwa, e w rezultacie
dokonanej zmiany przestanie dziaa kod, zawarty w funkcji main( ).
Teraz utwrz klas o nazwie Libc, zawierajc prywatne skadowe, bdce
acuchami a, b i c, a take funkcje skadowe seta( ), geta( ), setb( ), getb( ),
setc( ) i getc( ), umoliwiajce ustawianie i pobieranie wartoci skadowych.
W podobny sposb jak poprzednio napisz funkcj main( ). Teraz zastp prywatne
skadowe a, b i c, prywatn tablic string s[3]. Zauwa, e mimo dokonanych
zmian, kod zawarty w funkcji main( ) nie przesta dziaa poprawnie.
3. Utwrz klas i globaln funkcj, bdc jej przyjacielem, operujc

na prywatnych danych tej klasy.


4. Utwrz dwie klasy, tak by kada z nich posiadaa funkcj skadow,

przyjmujc wskanik do obiektu drugiej klasy. W funkcji main( ) utwrz


egzemplarze obu obiektw i wywoaj w kadym z nich wymienione wczeniej
funkcje skadowe.
5. Utwrz trzy klasy. Pierwsza z nich powinna zawiera dane prywatne, a take

wskaza jako swoich przyjaci ca drug klas oraz funkcj skadow


trzeciej klasy. Zademonstruj w funkcji main( ), e wszystko dziaa poprawnie.
6. Utwrz klas Hen. Umie wewntrz niej klas Nest. Wewntrz klasy Nest

ulokuj klas Egg. Kada z klas powinna posiada funkcj skadow display( ).
W funkcji main( ) utwrz obiekty kadej z klas i wywoaj dla kadego z nich
funkcj display( ).
7. Zmodyfikuj poprzednie wiczenie w taki sposb, aby klasy Nest i Egg

zawieray dane prywatne. Okrel przyjaci tych klas, tak aby do ich danych
prywatnych miay dostp klasy, w ktrych s one zagniedone.

228

Thinking in C++. Edycja polska


8. Utwrz klas, ktrej dane skadowe zawarte bd w regionach: publicznym,

prywatnym i chronionym. Dodaj do klasy funkcj skadow showMap( ),


drukujc nazwy oraz adresy kadej z tych danych skadowych. Jeeli to
moliwe, skompiluj i uruchom program, uywajc rnych kompilatorw,
komputerw i systemw operacyjnych. Obserwuj, czy zmienia si ukad
danych skadowych w pamici.
9. Skopiuj pliki zawierajce implementacje i testy programu Stash, zawartego

w rozdziale 4., tak aby je skompilowa i uruchomi razem z zawartym


w biecym rozdziale plikiem Stash.h.
10. Zapamitaj obiekty klasy Hen, utworzonej w 6. wiczeniu, uywajc do tego

klasy Stash. Pobierz je ponownie, a nastpnie je wydrukuj (jeeli jeszcze


nie zostao to wykonane, naley utworzy funkcj skadow Hen::print( )).
11. Skopiuj pliki zawierajce implementacje i testy programu Stack, zawartego

w rozdziale 4., tak aby je skompilowa i uruchomi razem z zawartym


w biecym rozdziale plikiem Stack2.h.
12. Zapamitaj obiekty klasy Hen, utworzonej w 6. wiczeniu, uywajc do tego

klasy Stack. Pobierz je z powrotem ze stosu, a nastpnie wydrukuj (jeeli jeszcze


nie zostao to wykonane, naley utworzy funkcj skadow Hen::print( )).
13. Zmodyfikuj struktur Cheshire, zawart w pliku Handle.cpp, i sprawd,

czy twj meneder powtrnie skompiluje i poczy jedynie ten plik,


nie kompilujc ponownie pliku UseHandle.cpp.
14. Utwrz klas StackOfInt (stos przechowujcy wartoci cakowite) w klasie

o nazwie StackImp. Uyj do tego celu techniki kota z Cheshire, ukrywajcej


niskopoziomowe struktury danych, stosowane do przechowywania elementw.
Zaimplementuj dwie wersje klasy StackImp wykorzystujc tablic liczb
cakowitych o staym rozmiarze i stosujc typ vector<int>. Ustaw maksymaln
wielko stosu, by nie uwzgldnia powikszania tablicy w pierwszym z tych
przypadkw. Zwr uwag na to, e opis klasy, zawarty w pliku StackOfInt.h,
nie zmienia si podczas dokonywania zmian w klasie StackImp.

You might also like