You are on page 1of 22

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

TWJ KOSZYK

C++. Projektowanie
systemw informatycznych.
Vademecum profesjonalisty
Autor: John Lakos
Tumaczenie: Wojciech Moch (rozdz. 1 4), Micha Dadan
(rozdz. 5, 6), Radosaw Meryk (rozdz. 7 10, dod. A C)
ISBN: 83-7361-173-8
Tytu oryginau: Large-Scale C++ Software Design
Format: B5, stron: 688
Przykady na ftp: 52 kB

DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

C++ nie jest tylko rozszerzeniem jzyka C, ale wprowadza zupenie nowy model
programowania. Stopie skomplikowania C++ moe by przytaczajcy nawet dla
dowiadczonych programistw C, jednak zazwyczaj nie sprawia im problemw napisanie
i uruchomienie maego, niebanalnego programu w C++. Niestety, brak dyscypliny
dopuszczalny przy tworzeniu maych programw, zupenie nie sprawdza si w duych
projektach. Podstawowe uycie technologii C++ nie wystarczy do budowy duych
projektw. Na niezorientowanych czeka wiele puapek.
Ksika ta opisuje metody projektowania duych systemw wysokiej jakoci.
Adresowana jest do dowiadczonych programistw C++ prbujcych stworzy
architektur atw w obsudze i moliw do ponownego wykorzystania. Nie zawarto
w niej teoretycznego podejcia do programowania. W tej ksice znajduj si praktyczne
wskazwki wypywajce z wieloletnich dowiadcze ekspertw C++ tworzcych
ogromne systemy wielostanowiskowe. Autor pokazuje, jak naley projektowa systemy,
nad ktrymi pracuj setki programistw, skadajce si z tysicy klas i prawdopodobnie
milionw linii kodu.
W ksice opisano:

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

Tworzenie programw wieloplikowych w C++


Konstruowanie komponentw
Podzia projektu fizycznego na poziomy
Cakowit i czciow izolacj, reguy jej stosowania
Tworzenie pakietw i ich podzia na poziomy
Projektowanie funkcji
Implementowanie metod
Dodatki do ksiki opisuj przydatny wzorzec projektowy hierarchi protokow,
implementowanie interfejsu C++ zgodnego ze standardem ANSI C oraz pakiet sucy
do okrelania i analizowania zalenoci.

5RKUVTGEK



 


W.1. Od C do C++ ............................................................................................................... 15
W.2. Jak uywa C++ do tworzenia duych projektw ...................................................... 16
W.2.1. Zalenoci cykliczne........................................................................................ 16
W.2.2. Nadmierne zalenoci na etapie konsolidacji .................................................. 18
W.2.3. Nadmierne zalenoci na etapie kompilacji..................................................... 20
W.2.4. Globalna przestrze nazw................................................................................ 22
W.2.5. Projekt logiczny i fizyczny .............................................................................. 23
W.3. Ponowne uycie........................................................................................................... 25
W.4. Jako .......................................................................................................................... 25
W.4.1. Kontrola jakoci............................................................................................... 27
W.4.2. Zapewnienie jakoci ........................................................................................ 27
W.5. Narzdzia..................................................................................................................... 27
W.6. Podsumowanie ............................................................................................................ 28






 





1.1. Programy wieloplikowe w C++ .................................................................................... 31
1.1.1. Deklaracja a definicja.......................................................................................... 31
1.1.2. Konsolidacja (czenie) wewntrzna a zewntrzna ............................................. 33
1.1.3. Pliki nagwkowe (.h) ......................................................................................... 36
1.1.4. Pliki implementacji (.c) ....................................................................................... 37
1.2. Deklaracje typedef ........................................................................................................ 38
1.3. Instrukcje sprawdzajce ................................................................................................ 39
1.4. Kilka sw na temat stylu .............................................................................................. 40
1.4.1. Identyfikatory...................................................................................................... 41
1.4.1.1. Nazwy typw..........................................................................................41
1.4.1.2. Nazwy identyfikatorw skadajce si z wielu sw...............................42
1.4.1.3. Nazwy skadowych klas .........................................................................42
1.4.2. Kolejno uoenia skadowych w klasie ............................................................ 44
1.5. Iteratory......................................................................................................................... 46
1.6. Logiczna notacja projektu ............................................................................................. 52
1.6.1. Relacja Jest.......................................................................................................... 53
1.6.2. Relacja Uywa-W-Interfejsie .............................................................................. 54
1.6.3. Relacja Uywa-W-Implementacji ....................................................................... 56
1.6.3.1. Relacja Uywa........................................................................................58
1.6.3.2. Relacje Ma i Trzyma ..............................................................................58
1.6.3.3. Relacja By .............................................................................................59

C++. Projektowanie systemw informatycznych. Vademecum profesjonalisty

1.7. Dziedziczenie i warstwy................................................................................................ 60


1.8. Minimalizacja................................................................................................................ 61
1.9. Podsumowanie .............................................................................................................. 62

 


 


2.1. Przegld ........................................................................................................................ 65
2.2. Dostp do pl klasy....................................................................................................... 66
2.3. Globalna przestrze nazw ............................................................................................. 70
2.3.1. Dane globalne...................................................................................................... 70
2.3.2. Wolne funkcje ..................................................................................................... 72
2.3.3. Wyliczenia, stae i deklaracje typedef ................................................................. 73
2.3.4. Makra preprocesora............................................................................................. 74
2.3.5. Nazwy w plikach nagwkowych........................................................................ 75
2.4. Kontrola docze ......................................................................................................... 77
2.5. Dodatkowa kontrola docze....................................................................................... 79
2.6. Dokumentacja ............................................................................................................... 84
2.7. Sposoby nazywania identyfikatorw............................................................................. 86
2.8. Podsumowanie .............................................................................................................. 87



  

 


 


3.1. Komponenty a klasy...................................................................................................... 93
3.2. Reguy projektw fizycznych...................................................................................... 100
3.3. Relacja ZaleyOd........................................................................................................ 108
3.4. Zalenoci implikowane.............................................................................................. 112
3.5. Wydobywanie rzeczywistych zalenoci .................................................................... 117
3.6. Przyja ...................................................................................................................... 119
3.6.1. Przyja na odlego i zalenoci implikowane............................................... 122
3.6.2. Przyja i oszustwo........................................................................................... 124
3.7. Podsumowanie ............................................................................................................ 126

 


 !" #!


4.1. Metafora dla testowania oprogramowania .................................................................. 129
4.2. Zoony podsystem ..................................................................................................... 130
4.3. Problemy z testowaniem dobrych interfejsw ......................................................... 134
4.4. Projektowanie zorientowane na testowalno ............................................................. 136
4.5. Testowanie pojedynczych moduw ........................................................................... 138
4.6. Acykliczne zalenoci fizyczne................................................................................... 140
4.7. Numery poziomw...................................................................................................... 142
4.7.1. rda numeracji poziomw.............................................................................. 142
4.7.2. Uywanie numerw poziomw w oprogramowaniu ......................................... 144
4.8. Testowanie hierarchiczne i przyrostowe ..................................................................... 147
4.9. Testowanie zoonych podsystemw .......................................................................... 153
4.10. Testowalno kontra testowanie................................................................................ 154
4.11. Cykliczne zalenoci fizyczne................................................................................... 155
4.12. Suma zalenoci komponentw ................................................................................ 156
4.13. Jako projektu fizycznego ....................................................................................... 161
4.14. Podsumowanie .......................................................................................................... 167

 


   


5.1. Niektre przyczyny cyklicznych zalenoci fizycznych ............................................. 169
5.1.1. Rozszerzenie ..................................................................................................... 170
5.1.2. Wygoda ............................................................................................................. 172
5.1.3. Wewntrzna zaleno ...................................................................................... 176

Spis treci

5.2. Wyniesienie................................................................................................................. 178


5.3. Obnienie .................................................................................................................... 187
5.4. Nieprzezroczyste wskaniki........................................................................................ 199
5.5. Gupie dane ................................................................................................................. 206
5.6. Redundancja................................................................................................................ 216
5.7. Wywoania zwrotne .................................................................................................... 219
5.8. Klasa-meneder........................................................................................................... 231
5.9. Faktoring..................................................................................................................... 235
5.10. Wynoszenie enkapsulacji .......................................................................................... 249
5.11. Podsumowanie .......................................................................................................... 260

 


$% !&


6.1. Od enkapsulacji do izolacji ......................................................................................... 262
6.1.1. Koszty powiza na etapie kompilacji .............................................................. 266
6.2. Konstrukcje w jzyku C++ a zalenoci na etapie kompilacji .................................... 267
6.2.1. Dziedziczenie (Jest) a zalenoci na etapie kompilacji ..................................... 268
6.2.2. Podzia na warstwy (Ma/Trzyma) a zalenoci na etapie kompilacji ................ 269
6.2.3. Funkcje inline a zalenoci na etapie kompilacji............................................... 270
6.2.4. Skadowe prywatne a zalenoci na etapie kompilacji ...................................... 271
6.2.5. Skadowe chronione a zalenoci na etapie kompilacji ..................................... 273
6.2.6. Funkcje skadowe generowane przez kompilator a zalenoci
na etapie kompilacji ................................................................................................. 274
6.2.7. Dyrektywy include a zalenoci na etapie kompilacji....................................... 275
6.2.8. Argumenty domylne a zalenoci na etapie kompilacji ................................... 277
6.2.9. Wyliczenia a zalenoci na etapie kompilacji ................................................... 277
6.3. Techniki czciowej izolacji ....................................................................................... 279
6.3.1. Rezygnacja z dziedziczenia prywatnego ........................................................... 279
6.3.2. Usuwanie osadzonych danych skadowych....................................................... 281
6.3.3. Usuwanie prywatnych funkcji skadowych ....................................................... 282
6.3.4. Usuwanie skadowych chronionych .................................................................. 290
6.3.5. Usuwanie prywatnych danych skadowych....................................................... 299
6.3.6. Usuwanie funkcji generowanych przez kompilator........................................... 302
6.3.7. Usuwanie dyrektyw include .............................................................................. 302
6.3.8. Usuwanie argumentw domylnych.................................................................. 303
6.3.9. Usuwanie wylicze ........................................................................................... 305
6.4. Techniki cakowitej izolacji ........................................................................................ 307
6.4.1. Klasa protokou ................................................................................................. 308
6.4.2. W peni izolujca klasa konkretna..................................................................... 317
6.4.3. Izolujce komponenty otaczajce...................................................................... 322
6.4.3.1. Pojedyncze komponenty otaczajce .....................................................323
6.4.3.2. Wielokomponentowe warstwy otaczajce............................................331
6.5. Interfejs proceduralny ................................................................................................. 338
6.5.1. Architektura interfejsu proceduralnego ............................................................. 339
6.5.2. Tworzenie i usuwanie nieprzezroczystych obiektw ........................................ 341
6.5.3. Uchwyty ............................................................................................................ 342
6.5.4. Uzyskiwanie dostpu do nieprzezroczystych obiektw i manipulowanie nimi .... 346
6.5.5. Dziedziczenie a nieprzezroczyste obiekty ......................................................... 351
6.6. Izolowa czy nie izolowa .......................................................................................... 354
6.6.1. Koszt izolacji..................................................................................................... 354
6.6.2. Kiedy nie naley izolowa................................................................................. 356
6.6.3. Jak izolowa ...................................................................................................... 360
6.6.4. Do jakiego stopnia naley izolowa .................................................................. 366
6.7. Podsumowanie ............................................................................................................ 373

C++. Projektowanie systemw informatycznych. Vademecum profesjonalisty

 '


 (

''
7.1. Od komponentw do pakietw ................................................................................... 378
7.2. Zarejestrowane prefiksy pakietw............................................................................... 385
7.2.1. Potrzeba stosowania prefiksw ......................................................................... 385
7.2.2. Przestrzenie nazw.............................................................................................. 387
7.2.3. Zachowanie integralnoci pakietu ..................................................................... 391
7.3. Podzia pakietw na poziomy ..................................................................................... 393
7.3.1. Znaczenie podziau pakietw na poziomy......................................................... 393
7.3.2. Techniki podziau pakietw na poziomy........................................................... 394
7.3.3. Podzia systemu................................................................................................. 396
7.3.4. Wytwarzanie oprogramowania w wielu orodkach........................................... 398
7.4. Izolacja pakietw ........................................................................................................ 399
7.5. Grupy pakietw........................................................................................................... 402
7.6. Proces wydawania oprogramowania ........................................................................... 406
7.6.1. Struktura wydania ............................................................................................. 408
7.6.2. aty ................................................................................................................... 413
7.7. Program main.............................................................................................................. 415
7.8. Faza startu ................................................................................................................... 421
7.8.1. Strategie inicjalizacji ......................................................................................... 423
7.8.1.1. Technika przebudzenia w stanie zainicjowania ................................424
7.8.1.2. Technika jawnego wywoywania funkcji init .......................................424
7.8.1.3. Technika wykorzystania specjalnego licznika......................................426
7.8.1.4. Technika sprawdzania za kadym razem..............................................431
7.8.2. Porzdkowanie .................................................................................................. 432
7.8.3. Przegld............................................................................................................. 433
7.9. Podsumowanie ............................................................................................................ 434

  
 
  !  "#$
 )


&( ( *


8.1. Abstrakcje i komponenty ............................................................................................ 439
8.2. Projekt interfejsu komponentu .................................................................................... 440
8.3. Poziomy enkapsulacji.................................................................................................. 444
8.4. Pomocnicze klasy implementacyjne............................................................................ 454
8.5. Podsumowanie ............................................................................................................ 459

 


&( #(!&


9.1. Specyfikacja interfejsu funkcji.................................................................................... 462
9.1.1. Operator czy metoda?........................................................................................ 462
9.1.2. Wolny operator czy skadowa klasy? ................................................................ 468
9.1.3. Metoda wirtualna czy niewirtualna?.................................................................. 472
9.1.4. Metoda czysto wirtualna czy nie czysto wirtualna? .......................................... 476
9.1.5. Metoda statyczna czy niestatyczna? .................................................................. 477
9.1.6. Metody stae czy modyfikowalne? .................................................................... 478
9.1.7. Metody publiczne, chronione czy prywatne ...................................................... 483
9.1.8. Zwracanie wyniku przez warto, referencj czy wskanik? ............................ 484
9.1.9. Zwracanie wartoci typu const czy nie-const? .................................................. 487
9.1.10. Argument opcjonalny czy obowizkowy?....................................................... 488
9.1.11. Przekazywanie argumentw przez warto, referencj lub wskanik ............. 490
9.1.12. Przekazywanie argumentw jako const lub nie-const ..................................... 495
9.1.13. Funkcja zaprzyjaniona czy niezaprzyjaniona? ............................................. 496
9.1.14. Funkcja inline czy nie inline?.......................................................................... 497

Spis treci

9.2. Typy podstawowe uyte w interfejsie ......................................................................... 498


9.2.1. Uycie typu short w interfejsie.......................................................................... 498
9.2.2. Uycie kwalifikatora unsigned w interfejsie ..................................................... 501
9.2.3. Zastosowanie typu long w interfejsie ................................................................ 505
9.2.4. Zastosowanie typw float, double oraz long double w interfejsie..................... 507
9.3. Funkcje specjalnego przeznaczenia............................................................................. 508
9.3.1. Operatory konwersji .......................................................................................... 508
9.3.2. Semantyka wartoci generowanych przez kompilator....................................... 512
9.3.3. Destruktor.......................................................................................................... 513
9.4. Podsumowanie ............................................................................................................ 515

  +
 $ % ,(*


10.1. Pola ........................................................................................................................... 521
10.1.1. Wyrwnanie naturalne................................................................................... 522
10.1.2. Uycie typw podstawowych w implementacji............................................. 524
10.1.3. Uycie konstrukcji typedef w implementacji................................................. 526
10.2. Definicje funkcji ....................................................................................................... 527
10.2.1. Samokontrola ................................................................................................ 527
10.2.2. Unikanie przypadkw szczeglnych ............................................................. 528
10.2.3. Podzia zamiast powielania ........................................................................... 530
10.2.4. Zbytnia przebiego nie popaca .................................................................. 533
10.3. Zarzdzanie pamici................................................................................................ 533
10.3.1. Wartoci stanu logicznego i fizycznego ........................................................ 538
10.3.2. Parametry fizyczne ........................................................................................ 541
10.3.3. Systemy przydziau pamici .......................................................................... 545
10.3.4. Zarzdzanie pamici na poziomie klasy ...................................................... 551
10.3.4.1. Dodawanie wasnych mechanizmw zarzdzania pamici ...........555
10.3.4.2. Zablokowana pami ......................................................................558
10.3.5. Zarzdzanie pamici na poziomie obiektu................................................... 562
10.4. Uycie szablonw w duych projektach ................................................................... 567
10.4.1. Implementacje szablonw ............................................................................. 567
10.4.2. Zarzdzanie pamici w szablonach.............................................................. 568
10.4.3. Wzorce a szablony......................................................................................... 577
10.5. Podsumowanie .......................................................................................................... 579

%
&'#
- (. ! &(/!%  !"

)
Protocol Hierarchy struktury klas.................................................................................. 585
Cel ............................................................................................................................. 585
Znany te jako ........................................................................................................... 585
Motywacja................................................................................................................. 585
Zakres zastosowania.................................................................................................. 589
Struktura.................................................................................................................... 590
Elementy skadowe.................................................................................................... 590
Wsppraca................................................................................................................ 591
Konsekwencje ........................................................................................................... 591
Implementacja ........................................................................................................... 592
Przykadowy kod....................................................................................................... 603
Znane zastosowania................................................................................................... 607
Pokrewne wzorce ...................................................................................................... 608

10

C++. Projektowanie systemw informatycznych. Vademecum profesjonalisty

- (0

$ % #&122
  .34$1


B.1. Wykrywanie bdu alokacji pamici........................................................................... 611
B.2. Definiowanie procedury main (tylko ANSI C)........................................................... 618

- (1  ((5%    %   %65!


C.1. Korzystanie z polece adep, cdep i ldep..................................................................... 622
C.2. Dokumentacja wiersza polecenia ............................................................................... 633
C.3. Architektura pakietu idep ........................................................................................... 643
C.4. Kod rdowy ............................................................................................................. 646

- (- 7((

'
D.1. Definicje..................................................................................................................... 647
D.2. Gwne reguy projektowe ......................................................................................... 652
D.3. Poboczne reguy projektowe ...................................................................................... 653
D.4. Wskazwki................................................................................................................. 654
D.5. Zasady ........................................................................................................................ 657

0,% #

'
4(

'

Rozdzia 9.

2TQLGMVQYCPKGHWPMELK
Celem projektowania funkcji jest zapewnienie atwego i wydajnego dostpu do operacji
zdefiniowanych przez abstrakcj. Jzyk C++ zapewnia swobod definiowania interfejsu
na poziomie funkcji. Czy funkcja ma by operatorem, metod lub wolnym operatorem,
w jaki sposb bd przekazywane argumenty oraz w jaki sposb bd przekazywane
wyniki to elementy nalece do tego etapu procesu projektowania. Styl programowania to tylko jeden z elementw, ktre odgrywaj rol w podejmowaniu tego typu decyzji projektowych. Wiele z nich zostanie omwionych w niniejszym rozdziale.
W jzyku C++ mamy do dyspozycji wiele odmian podstawowych typw reprezentujcych liczby cakowite (jak np. ,  
,  itp.). Typy te zapewniaj dodatkow swobod. Nierozwane ich wykorzystanie moe skomplikowa lub nawet osabi
interfejs.
Operator konwersji dla typw definiowanych przez uytkownika umoliwia kompilatorowi wykonywanie niejawnej konwersji na lub z typu definiowanego przez uytkownika.
Uwane projektowanie wymaga przeanalizowania moliwych zalet niejawnej konwersji
w zestawieniu z niejednoznacznociami oraz moliwoci powstania bdw w zwizku
z obnieniem bezpieczestwa typw. Niektre inne funkcje, w przypadku gdy nie zostan
okrelone jawnie, gdy zajdzie taka potrzeba mog by zdefiniowane automatycznie przez
kompilator. Podjcie decyzji dotyczcych dopuszczalnoci generowania definicji funkcji przez kompilator wymaga uwanej analizy.
W tym rozdziale opiszemy szkielet projektowania interfejsu komponentu na poziomie
pojedynczej funkcji. Omwimy obszern przestrze projektow dostpn dla autorw
komponentw i wskaemy decyzje projektowe, ktre s korzystne lub niekorzystne.
Przekonamy si, ile poziomw swobody w przestrzeni projektu interfejsu funkcji mona
wyeliminowa bez strat w skutecznoci. Uzyskany szkielet pomoe nam opracowywa
interfejsy prostsze, bardziej jednolite i atwiejsze do utrzymania.

462

Cz III  Zagadnienia dotyczce projektu logicznego

5RGE[HKMCELCKPVGTHGLUWHWPMELK
Zgodnie z podstawowymi zasadami przedstawionymi w rozdziale 2., podczas okrelania interfejsu funkcji w jzyku C++ naley zwrci uwag na kilka aspektw:


Czy funkcja jest operatorem, czy nim nie jest?



Czy jest wolnym operatorem, czy elementem skadowym klasy?



Czy jest to metoda wirtualna, czy niewirtualna?



Czy jest to metoda czysto wirtualna, czy te nie czysto wirtualna?



Metoda staa czy modyfikowalna?



Metoda typu  czy nie-?



Metoda publiczna ( ), chroniona (



) czy prywatna (
)?

Wynik zwracany przez warto, referencj czy wskanik?

Zwracany wynik typu  czy nie-?

 

Argument opcjonalny czy obowizkowy?



Argumenty przekazywane przez warto, referencj czy wskanik?



Przekazywane argumenty typu  czy nie-?

Istniej take dwa aspekty dotyczce organizacji, ktre naley wzi pod uwag, pomimo tego, e nie s one czci logicznego interfejsu:


Czy jest to funkcja zaprzyjaniona, czy te nie?



Funkcja typu inline, czy nie typu inline?

Pomidzy tymi aspektami istnieje wiele wzajemnych zalenoci. Zazwyczaj odpowied


na jedno z pyta ma wpyw na odpowied na inne. W dalszej czci niniejszego rozdziau
omwimy wymienione zagadnienia osobno i podamy wskazwki umoliwiajce podjcie
optymalnych decyzji projektowych1.


 
 
Oprcz operatorw generowanych przez kompilator (np. przypisania), jedynym powodem utworzenia z funkcji operatora jest wygodna notacja wewntrz klientw. Zwrmy
uwag, e inaczej ni w przypadku notacji typowej dla funkcji, notacja operatorowa nie
zaley od kontekstu wywoanie funkcji w wyniku interpretacji operatora wywoanego przez metod bdzie takie samo jak w przypadku wywoania w zasigu pliku2. Rozwane wykorzystywanie przeciania operatorw ma naturaln i oczywist przewag
nad notacj funkcyjn w szczeglnoci w przypadku typw logicznych i arytmetycznych definiowanych przez uytkownika.
1

Zobacz te meyers, pozycja 19, str. 70.

ellis, punkt 13.4.1, str. 332.

Rozdzia 9.  Projektowanie funkcji

463

Przeanalizujmy dwa rne modele skadni pokazane na listingu 9.1 odpowiadajce


dwm rnym interfejsom dla komponentu zbioru liczb cakowitych 
.
Na listingu 9.1a pokazano skuteczny sposb zastosowania notacji operatorowej.
Natura abstrakcji zbioru powoduje, e znaczenie tych operatorw staje si intuicyjne nawet dla tych programistw, ktrzy nie znaj pokazywanego komponentu. Na
listingu 9.1b pokazano odpowiednik skadni z zastosowaniem bardziej nieporcznej
notacji funkcyjnej3.

Dwa modele skadni dla abstrakcji zbioru liczb cakowitych

 

 


 

 

 

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

 

       

    

" # $ %


" & # '
 !  ,, 
 !  ,, 
 !  ,,  
 !  ,,
 ,,
 ,,
 ,, 


 ,,
 ,,  



 ,,
 ,, 




 *
+

 ,,    

(a) z przecianiem operatorw

(b) bez przeciania operatorw

 *
+

Podstawowym powodem stosowania mechanizmu przeciania operatorw powinna


by czytelno (w wikszym stopniu ni atwo uywania).
3

Niektre metody zdefiniowano jako statyczne, aby umoliwi t sam symetryczn niejawn konwersj
argumentw, jak w przypadku odpowiadajcych im operatorw (patrz punkt 9.1.5). Styl akapitw gboko
zagniedonych wywoa funkcji na rysunku 9.1b zapoyczono z takich jzykw, jak LISP i CLOS, gdzie
takie konstrukcje wystpuj bardzo czsto.

464

Cz III  Zagadnienia dotyczce projektu logicznego

W omawianej aplikacji obsugi zbioru liczb cakowitych notacja operatorowa w oczywisty sposb poprawia zarwno czytelno, jak te atwo uywania. Przez czytelno
rozumiemy zdolno inyniera oprogramowania do rozrniania w szybki i precyzyjny
sposb znanego kodu treci funkcji od nieznanego kodu rdowego. atwo uywania
dotyczy tego, jak atwo programista moe skutecznie wykorzysta obiekt w celu utworzenia nowego oprogramowania. Zazwyczaj kod rdowy odczytuje si wicej razy,
ni si go zapisuje (w przypadku wikszoci duych, wykorzystywanych przez dugi
okres czasu systemw oprogramowania, koszty utrzymania przekraczaj koszty wytwarzania od 2 do 4 razy4).
Semantyka przecionych operatorw powinna by naturalna, oczywista i intuicyjna
dla klientw.

Podczas projektowania czsto mona otrzyma zgrabne i atwe w uyciu aplikacje operatorw, ktre nie maj intuicyjnego znaczenia dla programistw, nie znajcych naszego
komponentu. Nierozsdne stare przyzwyczajenia, jak np. zdefiniowanie jednoargumentowego operatora  jako skadowej klasy  w celu odwrcenia kolejnoci znakw w cigu, jest nie na miejscu w rodowisku projektowym duej skali. Papierkiem
lakmusowym odpowiadajcym na pytanie czy zastosowa notacj operatorow powinno by stwierdzenie, czy istnieje naturalne i intuicyjne znaczenie natychmiast zrozumiae dla nowych klientw, ktre poprawia poziom czytelnoci (lub przynajmniej go
nie pogarsza)5.
Syntaktyczne waciwoci przecionych operatorw dla typw definiowanych przez
uytkownika powinny by lustrzan kopi waciwoci zdefiniowanych dla typw
podstawowych.

Na poziomie semantycznym do trudno dostarczy szczegowych wskazwek odnonie tego co jest, a co nie jest intuicyjne. Jednak na poziomie syntaktycznym, biorc za
podstaw implementacj podstawowych typw jzyka, mona sformuowa kilka zdecydowanych i dobrze zdefiniowanych stwierdze.
Wzorowanie syntaktycznych waciwoci operatorw zdefiniowanych przez
uytkownika na predefiniowanych operatorach C++ pozwala na uniknicie
niespodzianek i sprawia, e sposb ich uywania jest atwiejszy do przewidzenia.

W jzyku C++ kade wyraenie ma warto. Istniej dwa podstawowe typy wartoci
tzw. lwartoci (ang. lvalue) oraz pwartoci (ang. rvalue)6. Lwarto to taka warto, dla
ktrej mona wyznaczy adres. Jeeli lwarto moe si znale po lewej stronie wyraenia przypisania, mwi si o niej, e jest modyfikowalna, w innym przypadku okrela
si j jako lwarto niemodyfikowaln7. Do pwartoci nie mona przypisa wartoci, ani
4

sommerville, punkt 1.2.1, str. 10.

Patrz te cargill, rozdzia 5., str. 91.

Pojcia te pochodz z klasycznego jzyka C: pojcie lwarto oznacza, e warto wyraenia moe si
znale po lewej stronie instrukcji przypisania, natomiast pwarto moe si znale wycznie po jej
prawej stronie. Wraz z pojawieniem si konstrukcji  w jzyku C++ i ANSI C, lwartoci dzieli si
teraz na dwie odmiany: modyfikowalne i niemodyfikowalne (patrz stroustrup, punkt 2.1.2, str. 46 47).

ellis, podrozdzia 3.7, str. 25 26.

Rozdzia 9.  Projektowanie funkcji

465

nie mona pobra jej adresu8. Najprostsz lwartoci jest identyfikator zmiennej. Jeeli
zmienna nie jest zadeklarowana jako , jest to lwarto modyfikowalna. Niektre
operatory, jak np. operator przypisania () i jego odmiany (      
   !!), preinkrementacji (") i predekrementacji (") zastosowane do typw podstawowych, zwracaj modyfikowalne lwartoci. Operatory te zawsze zwracaj
zapisywaln referencj do modyfikowanego argumentu. Np. hipotetyczna definicja operatorw dla podstawowego typu 
(w przypadku jego implementacji jako klasy
C++) moe mie posta tak, jak pokazano na listingu 9.2.
 Hipotetyczna implementacja podstawowego typu double
    -- ./0,   / / 1234 5
--
 ,
  +
 
   6
7  +
 6  !  6 
 6   !  6 
 6  )!  6 
 6  (!  6 
 6  -!  6 
 6    -- 41 8
 6  )) -- 41 ))8
     -- 41 8
   )) -- 41 8))
  ( 6 -- 10/3   
   ( 6  -- 10/3   
+
      6  -- 10/3
   )  6  -- 10/3 )
  9  6  -- 10/3 023  


  66  6    6 0


  ::  6    6 0
      6    6 0
   )  6    6 0
   (  6    6 0
   -  6    6 0
  !!  6    6 0
  9!  6    6 0
     6    6 0
  !  6    6 0
     6    6 0
  !  6    6 0

Pola bitowe s wyjtkiem w tym sensie, e mog si znale po lewej stronie wyraenia przypisania, ale zgodnie
z ARM (ellis, podrozdzia 9.6, str. 184) nie mona wyznaczy ich adresu. Zasada ta dotyczy take zmiennych
tymczasowych typw zdefiniowanych przez uytkownika, ktre nie posiadaj nazwy (patrz punkt 9.1.2).

466

Cz III  Zagadnienia dotyczce projektu logicznego

Inne operatory pokazane na listingu 9.2 zwracaj pwarto, poniewa nie ma moliwoci
zwrcenia odpowiedniej lwartoci. W przypadku symetrycznych operatorw binarnych
(jak np.  oraz ) warto do zwrcenia nie jest ani argumentem lewym, ani prawym, ale
now wartoci uzyskan na podstawie obydwu, a zatem wynik musi by zwrcony przez
warto9. Operatory rwnoci (, #) oraz operatory relacyjne (!, !, , ) zawsze zwracaj
pwarto typu  o wartoci 0 lub 1, a zatem i w tym przypadku aden z argumentw
wejciowych nie jest odpowiedni wartoci do zwrcenia. Operatory postinkrementacji
i postdekrementacji to interesujcy przypadek specjalny w tym sensie, e s to jedyne
operatory, ktre modyfikuj obiekt, a zatem nie ma odpowiedniej lwartoci do zwrcenia:
   ,,  

   ! (
(
  
+

   ,, ))



   ! (
))(
  
+

Jako bardziej subtelny przykad przeanalizujmy dwa modele skadni odpowiadajce abstrakcji oglnej tabeli symboli, pokazane na listingu 9.3. W obu przypadkach na podstawie parametru typu  tworzona jest tabela symboli, dodawane s dwa symbole, a nastpnie poszukuje si parametru foo wedug nazwy. Poniewa moliwe jest, e w tabeli
nie ma symbolu o okrelonej nazwie, zatem funkcja wyszukujca nie powinna zwraca
wyniku przez warto, ani przez referencj tak wic wynik jest zwracany przez wskanik (zwrmy uwag na to, w jaki sposb i do jakiego stopnia wykorzystano zalety enkapsulacji). Porwnajmy t sytuacj z zastosowaniem operatora $% w odniesieniu do tablicy
wartoci . Spodziewamy si uzyska referencj do poindeksowanej wartoci, nie za
wskanik, ktry moe mie warto  . Ta rnica w skadni pomidzy zastosowaniem operatora $% na listingu 9.3a oraz zastosowaniem operatora $% dla typw podstawowych powoduje, e notacja z wywoaniem funkcji pokazana na listingu 9.3b jest w tym
przypadku lepsza. Zarezerwowanie notacji operatorowej dla tych przypadkw, kiedy
skadnia stanowi lustrzane odbicie odpowiadajcej jej skadni dla typw podstawowych,
wzmacnia skuteczno przeciania operatorw.
 Dwa modele skadni dla abstrakcji oglnej tabeli symboli

0 3 


0 3 

 

0 3;  


 " --  


 & --23 3
  (< ! =

>
-- 

 

0 3;  


 "


 &
  (< ! 4 


-- 

(a) z przecianiem operatorw

(b) bez przeciania operatorw

Na listingu 9.4. zestawiono deklaracje wikszoci operatorw jzyka C++ w postaci,


w jakiej uyto by ich w odniesieniu do podstawowych typw jzyka (podstawowe operatory     &' nie daj zbyt wielu informacji).
9

Bardziej szczegowe objanienie znajduje si w meyers, pozycja 23, str. 82 84.

Rozdzia 9.  Projektowanie funkcji

467

 Podsumowanie waciwoci niektrych podstawowych operatorw


--  3   3 41
 ; 
;6    -- 8 ))8  4
;    -- 8 8))  4
;(  6 -- 68 10/3
 ;(  6  -- 68 10/3
;6  ! ;6 -- ! ! )! (! -! ?! ! ! 6! @! :!
+
;  ) ;6 -- ) 7 10/
  9 ;6 -- 9 10/3
;    ;6  ;6 -- ) ( -   ? 6 @ :
  !! ;6  ;6 -- !! 9!  !  !
  66 ;6  ;6 -- 66 ::
-- / 23 4 3 / /  /424/   A ! ;(
 A 
;6  =>  --   4/1  3 /0/3
;6  (  -- 234 /423/1 1 10/3
+
-- / 23 4 3 / /  /424/     A5 !  ;(
 A5 
 ;6  =>  --   4/1  3 /0/3
 ;6  ( -- 234 /423/1 1 /0/3
+

Zwrmy uwag, e operatory jednoargumentowe, ktre nie modyfikuj argumentw,


nie musz by skadowymi. Przykadowo, jednoargumentowy operator # z powodzeniem
dziaa dla typu zdefiniowanego przez uytkownika, jak np. 
(, pomimo tego, e dla
tego typu nie zdefiniowano operatora #:



< 06 



 9 
 
B /31C/3 1 /DC/3
  

+
-- 
+

Kod pokazany powyej dziaa dlatego, poniewa typ 


( wie, w jaki sposb ma si
przeksztaci na podstawowy typ ( ), dla ktrego zdefiniowano operator #. Gdyby
operator # potraktowano jako skadow hipotetycznej definicji klasy  , nie mona
byoby wykona zdefiniowanej przez uytkownika konwersji, a wykonanie pokazanego
powyej kodu zakoczyoby si bdem kompilacji.
Aby wyczy moliwo niejawnej konwersji argumentw wolnego jednoargumentowego
operatora #, naley zdefiniowa operacj # jako metod np. )*&' zamiast operatora10.
10

Patrz te murray, podrozdzia 2.5, str. 44.

468

Cz III  Zagadnienia dotyczce projektu logicznego

  


     
Decyzja dotyczca tego, czy funkcja definiujca operator ma by skadow klasy, czy
woln funkcj, zaley od tego, czy podana jest niejawna konwersja typu skrajnego
lewego operandu. Jeeli operator modyfikuje ten operand, wwczas taka konwersja nie
jest podana.
Jzyk C++ sam w sobie jest obiektywnym i waciwym standardem, wedug ktrego
naley modelowa operatory definiowane przez uytkownika.

Zastanwmy si nad tym, co mogoby si zdarzy, gdybymy zdefiniowali operator


konkatenacji () dla klasy  jako woln funkcj, zamiast emulacji podejcia zapoyczonego z typw podstawowych. Zgodnie z tym, co pokazano na rysunku 9.1, utworzenie operatora  jako wolnej funkcji umoliwio niejawn konwersj jego lewego operandu
  na tymczasowy obiekt  (oznaczony tu jako ++,) o wartoci foo.
Chocia w przypadku typw podstawowych ta zmienna tymczasowa byaby pwartoci,
to wanie do tymczasowego obiektu  doczono warto bar (bez powstania
bdu kompilacji)11. Poniewa takie dziaanie zaskoczyoby i zdenerwowao uytkownikw, dobrze byoby, aby je wyczy.


Efekt implementacji
operator+=
jako wolnej funkcji

11

Obecnie w jzyku C++ dozwolone jest modyfikowanie nienazwanych tymczasowych zmiennych typu
zdefiniowanego przez uytkownika nieposiadajcych nazwy. Patrz murray, punkt 2.7.3, str. 53 55.

Rozdzia 9.  Projektowanie funkcji

469

Z drugiej strony spodziewamy si, e niektre operatory (np.  oraz ) bd dziaa bez
wzgldu na kolejno ich argumentw. Przeanalizujmy operator , ktry suy do konkatenacji dwch cigw znakw i zwraca wynik swojego dziaania przez warto. Jzyk
C++ pozwala na zdefiniowanie operatora  jako skadowej lub nieskadowej. To samo
dotyczy operatora . Jeeli zdecydujemy si na zdefiniowanie tych operatorw jako
skadowych, wwczas narazimy si na moliwo nastpujcego, nienormalnego dziaania naszych klientw:
< 

 0 

 


 
 ! 

 --  2
 !

 -- 
 !  !!

 --  2
 !

!!  -- 
+

Problem polega na tym, e deklaracje:


 0,,   06 0

oraz
 0,, !! 06 0

umoliwiaj niejawn konwersj typu   na  po prawej stronie za pomoc


konstruktora nastpujcej postaci:
 0,,  0  (

natomiast taka konwersja dla argumentu po lewej stronie nie jest moliwa12. Jeeli operatory te bd wolne, problem symetrii dla klasy  zostanie rozwizany, do
czasu dodania operatora konwersji:
 0,,    ( 

Na listingu 9.5 pokazano problem powstay w wyniku dodania operatora konwersji (rzutowania) z typu  na   . Co jest do dziwne, dwa niewtpliwie
podobne operatory  oraz  nie s identyczne pod wzgldem przeciania, w co (niestety
naiwnie) chcielibymy wierzy. Rnica polega na tym, e teraz istniej dwa sposoby
interpretacji operatora :


Jawna konwersja typu   na  i porwnanie za pomoc



&     '.



Niejawna konwersja typu  na    i porwnanie za pomoc


wbudowanego operatora  dla typw wskanikowych.

Taki problem nie istnieje dla operatora , poniewa w jzyku C++ nie ma sposobu
dodania dwch typw wskanikowych i dlatego w tym przypadku nie ma niejednoznacznoci.

12

ellis, punkt 13.4.2, str. 333.

470

Cz III  Zagadnienia dotyczce projektu logicznego

  Niejednoznacznoci wynikajce z zastosowania dwch operatorw konwersji


--  0
-- 
  0 
--
 ,
 0  ( 
--
    (  -- !! /3   4/1
+
  !! 06   06 0
0    06   06 0
-- 


 0

< 

 0 

 


 
 ! 

 --  2
 !

 --  2
 !  !!

 --  122
 !

!!  --  122
 !  --  2
+

W przypadku klasy  wykorzystywanej w praktyce nie bdziemy polega na niejawnej konwersji w celu uzyskania wartoci znakowej, ze wzgldu na obaw, e taka
dodatkowa konstrukcja i destrukcja spowoduje zbytni spadek wydajnoci. Zamiast tego
zdefiniujemy osobne przecione wersje operatora , ktrych zadaniem bdzie jak najbardziej wydajna obsuga kadej z trzech moliwoci, a tym samym rozwizanie problemw niejednoznacznoci.
Niespjnoci powstae w wyniku przeciania operatorw mog by oczywiste,
denerwujce i kosztowne dla uytkownikw.

Zgodnie z tym, co pokazano na listingu 9.6, dla umoliwienia zaakceptowania wartoci


   po lewej stronie operatora  jestemy zmuszeni do zdefiniowania co
najmniej jednej z funkcji operatorw porwnania jako wolnej funkcji.
  Wynik zaimplementowania operatora == jako funkcji skadowej
  0 
-- 
 ,
 0  ( 
    ( 
  !!  (   -- 23 3, 3323
-- .2/ 4/1 2/ 22 234/4 34
--  0/  /1   

Rozdzia 9.  Projektowanie funkcji

471

+
  !!  06    06 0
  !!  (   06 0
-- .2/ 332 4/1 2/ 22 234/4
--  0/ 2/  /1 14  /1   
 E 
E
    06  
-- F1/ 4/1 3  E   0
+
 G 
G
    ( 
-- F1/ 4/1 3  G    (
+
< 0

E 
G 
   !!   --  2, G !!   (
--  E !!   06
+
  H   -- , E !FI!   06
--  G !!   (
+
+

Na czym polega problem zdefiniowania jednej wersji funkcji 


 jako skadowej
w przypadku, gdy zdefiniowano wszystkie trzy wersje tego operatora? Ot problem
polega na tym, e brak symetrii mgby zaskoczy uytkownikw. W przypadku gdy
jeden obiekt moe by niejawnie przeksztacony na  , a drugi na  ,
spodziewamy si, e porzdek porwnania jest nieistotny. Jeeli zatem konstrukcja -
kompiluje si bez problemw, podobnie powinno by w przypadku zapisu -
(wyniki wykonania obu konstrukcji powinny by identyczne). Jednak jeeli wersja:
  !!  06   (

nie bdzie dostpna jako wolna funkcja, wwczas nie bdzie sposobu przeprowadzenia
nastpujcej konwersji:

472

Cz III  Zagadnienia dotyczce projektu logicznego

Wniosek jest taki, e operator  zawsze powinien by zdefiniowany jako wolna funkcja niezalenie od zastosowania innych funkcji. Te same powody dotycz innych operatorw dwuargumentowych, ktre nie modyfikuj adnego z operandw i zwracaj swj
wynik przez warto.
Przykad, jaki daje sam jzyk, jest bezstronnym i uytecznym modelem, ktry moe
suy klientom do tworzenia podstawowych syntaktycznych i aksjomatycznych waciwoci operatorw. Celem modelowania podstawowych operacji nie jest umoliwianie niejawnych konwersji samo w sobie, ale raczej zapewnienie symetrii po to, by unikn niespodzianek. W przypadku zastosowania przeciania operatorw w szerokim
zakresie naley si spodziewa, e abstrakcja moe by wykorzystywana wielokrotnie
w wielu sytuacjach. Uytkownicy komponentw wielokrotnego uytku doceni spjny
i profesjonalny interfejs niezalenie od syntaktycznych niespodzianek. Zwrmy uwag
na to, e w jzyku C++ wymagane jest, aby zdefiniowa jako skadowe nastpujce
operatory13:
!

przypisania,

=>

indeksu,

)

dostpu do skadowej klasy,



wywoania funkcji,

;

konwersji,

/

przydzia pamici (statyczny),



zwolnienie pamici (statyczne).


 
   
  
Dynamiczne wizanie umoliwia definiowanie metod, do ktrych dostp odbywa si za
pomoc klasy podstawowej, przez rzeczywisty podtyp obiektu, w odrnieniu do typu
wskanika lub referencji uytej w wywoaniu. W celu zapewnienia dynamicznego wizania funkcj naley zadeklarowa jako wirtualn ( ). W jzyku C++ wirtualne
mog by tylko metody. Jednak wniosek, e polimorficzne dziaanie operatora wymaga,
aby sta si funkcj skadow, gdy w innym przypadku byby woln funkcj, jest bdny.
W celu osignicia polimorficznego dziaania operatorw nie trzeba narusza
zagadnie syntaktycznych, jak np. symetrycznej niejawnej konwersji operatorw
dwuargumentowych.

Na rysunku 9.2 pokazano, w jaki sposb operatory symetryczne mog i powinny pozosta operatorami wolnymi pomimo zastosowania poliformizmu. Zamiast przeksztacania kadego z szeciu operatorw porwna i relacji na wirtualne metody klasy, opracowano jedn wirtualn metod porwnawcz. Te sze operatorw w dalszym cigu
bdzie dziaa symetrycznie bez wzgldu na niejawn konwersj dowolnego typu.

13

ellis, podrozdzia 12.3c, str. 306; stroustrup94, punkt 3.6.2, str. 82 83.

Rozdzia 9.  Projektowanie funkcji

473


Polimorficzne
porwnanie figur
geometrycznych
za pomoc wolnych
operatorw
-- 0  
 F5J.KIK LIMN OPAI
 F5J.KIK LIMN OPAI
 0   
 ,
< 70  
<  < (  ! *
<    0  6    ! *
-- Q/ 2  1 2   22  0
-- 23  4 0   1  / 123 /3 23
/423 
-- 40 0  4 0  
+
   !! 0  6   0  6 0 
  0 !! * +
   9! 0  6   0  6 0 
  0 9! * +
   ! 0  6   0  6 0 
  0 ! * 
    0  6   0  6 0 
  0  * +
   ! 0  6   0  6 0 
  0 ! * +
    0  6   0  6 0 
  0  * 


Operatory porwna czsto maj sens nawet wtedy, gdy operatory relacji nie maj sensu
(wemy pod uwag abstrakcj punktu). Czasami sortowanie heterogenicznych kolekcji
pozwala na uzyskanie wydajniejszego dostpu. W takich przypadkach przydaje si wykorzystanie porzdkowania (dowolnego typu). Wirtualna metoda  . &' pokazana
na rysunku 9.2 pozwala na zdefiniowanie wasnego identyfikatora typu fazy wykonania14.
Dziki wykorzystaniu tego identyfikatora mona sortowa figury tego samego typu wykorzystujc zdefiniowany dla nich indywidualny porzdek, natomiast sortowanie innych
typw mona zdefiniowa za pomoc innego (zupenie dowolnego) porwnania. Implementacj klasy
(/
wykorzystywanej do porzdkowania figur pokazano na listingu 9.7.
Metody wirtualne implementuj rnice w dziaaniu, natomiast pola rnice
w wartociach.
14

Patrz ellis, podrozdzia 10.2, str. 212 213.

474

Cz III  Zagadnienia dotyczce projektu logicznego

  Implementacja polimorficznego porwnania dla klasy geom_Circle


-- 0 
 F5J.KIK LIMN 5R5JI
 F5J.KIK LIMN 5R5JI
 F5J.KIK LIMN OPAI

0  


 0 5 ,   0   
  < (  
   
 ,
0 5   ,   +
0 5 0 56  ,    +
70 5 0 56 
0 56  ! 0 56  
  !    ( +
 < (       +
   0  6    -- /
   0 56   -- /
+
    0 56   0 56 0 
  0  * +
--  1 23 $  / 3323 


-- 0 

0 

 < (0 5,,  ! 6   -- 3  23


/34
0 5,,70 5 + --      2 4 S##
 0 5,,  0  6   

   !   T
  0 56   , -- / 1
     T )" , " -- / 3 /
+
 0 5,,  0 56  

      T )" ,     
+

Oglnie rzecz biorc, metody wirtualne su do opisania rnic w dziaaniu pomidzy


typami pochodzcymi od wsplnej klasy bazowej, natomiast wirtualne pola su do
opisania rnic wartoci i pozwalaj na uniknicie stosowania dziedziczenia15. Np. nie
bdziemy definiowa klasy-protokou / , by potem utworzy klasy pochodne
0
, 1 
i 2
3. Lepszym rozwizaniem w tej sytuacji bdzie zdefiniowanie
15

Patrz cargill, rozdzia 1, str. 16 19.

Rozdzia 9.  Projektowanie funkcji

475

jednej (w peni odizolowanej) klasy / , w ktrej zapisano by jeden z kilku wymienionych kolorw w postaci typu wyliczeniowego. Zastosowanie metod wirtualnych
jest jednak skuteczn technik rozwizywania problemu zalenoci zarwno fazy kompilacji, jak i konsolidacji (patrz punkt 6.4.1). Z tego powodu mona zdecydowa si na
utworzenie konkretnej klasy pochodnej na podstawie oglnej klasy / .
Ukrywanie: Metoda ukrywa funkcj o tej samej nazwie zadeklarowan
w ramach klasy podstawowej lub w zasigu pliku.
Przecianie: Funkcja przecia inn funkcj o tej samej nazwie zdefiniowan
w tym samym zasigu.
Przesanianie: Metoda przesania identyczn metod, ktr w klasie bazowej
zadeklarowano jako wirtualn.
Przedefiniowywanie: Domylna definicja funkcji jest nieodwracalnie zastpowana
inn definicj.

Na koniec zdefiniujemy cztery powszechnie uywane (czsto bdnie), podobne do siebie, pojcia suce do opisania funkcji i efektw ich dziaania na inne funkcje (ukrywanie, przecianie, przesanianie i przedefiniowywanie). O rnych funkcjach o tej samej
nazwie mwi si, e s przecione tylko wtedy, gdy zadeklarowano je w tym samym
zasigu. Jeeli metod klasy pochodnej zadeklarowano z identycznym interfejsem do
metody zadeklarowanej w klasie bazowej jako wirtualn, wwczas mwi si, e ta funkcja przesania metod klasy bazowej. We wszystkich pozostaych przypadkach, nazwa
funkcji ukrywa wszystkie inne funkcje o identycznej nazwie w tym samym zasigu,
niezalenie od ich sygnatur argumentw. Do funkcji ukrytych w danym zasigu nie ma
bezporedniego dostpu, chocia mona uzyska do nich dostp za pomoc operatora
zasigu (44). Jeeli jednak przedefiniujemy funkcj (np. globalny operator 
3 lub jednoargumentowy operator klasy ), czyli zamienimy jej definicj, wwczas jej poprzednia definicja nie bdzie ju dostpna16.
Naley unika ukrywania metod klasy bazowej w klasie pochodnej.

Naley uwaa, aby nie ukrywa definicji metod klasy bazowej w obrbie klas pochodnych. Nie naley zwaszcza tworzy nowych definicji dla niewirtualnych metod w klasie pochodnej, poniewa w takim przypadku takie metody bd wraliwe na typy wskanikw oraz adresw, spod ktrych bd wywoywane17. Umoliwienie powstania
zalenoci typu wskanikw lub adresw od tego, ktra funkcja bdzie wywoana, jest
dziaaniem antyintuicyjnym, subtelnym i powodujcym moliwo powstania bdw.
Ukrywanie metod zdefiniowanych w klasach bazowych nie wyklucza moliwoci ich
uycia, a jedynie utrudnia ich wykorzystanie. Aby wywoa ukryt metod, zawsze mona wykona pewne dziaania ze wskanikiem lub posuy si operatorem zasigu. Najlepiej stara si unika ukrywania metod. Przykady wzorcw projektowych obejmujcych wykorzystanie metod wirtualnych, wielokrotnego dziedziczenia oraz identyfikacji
typu w fazie wykonania zaprezentowano w dodatku C.
16

ellis, podrozdzia 10.2, str. 210 oraz podrozdzia 13.1, str. 310.

17

Patrz meyers, pozycja 37, str. 130 132.

You might also like