SlideShare a Scribd company logo
1 of 20
Download to read offline
IDZ DO
         PRZYK£ADOWY ROZDZIA£

                           SPIS TRE CI   C++. Strategie i taktyki.
                                         Vademecum profesjonalisty
           KATALOG KSI¥¯EK
                                         Autor: Robert B. Murray
                      KATALOG ONLINE     T³umaczenie: Przemys³aw Steæ
                                         ISBN: 83-7361-323-4
       ZAMÓW DRUKOWANY KATALOG           Tytu³ orygina³u: C++ Strategies and Tactics
                                         Format: B5, stron: 240

              TWÓJ KOSZYK
                    DODAJ DO KOSZYKA     Poznanie ruchów figur szachowych to dopiero pierwszy krok w nauce tej gry.
                                         Aby j¹ opanowaæ, trzeba zrozumieæ strategie i taktyki, które wp³ywaj¹ na ka¿dy ruch.
                                         To samo dotyczy jêzyka C++. Znajomo æ w³a ciwych strategii pomaga unikaæ pu³apek
         CENNIK I INFORMACJE             i pracowaæ o wiele skuteczniej. Rob Murray dziel¹c siê swoim do wiadczeniem pomaga
                                         programistom C++ wykonaæ nastêpny krok w kierunku tworzenia wydajnych aplikacji.
                   ZAMÓW INFORMACJE      Licznie wystêpuj¹ce w ca³ej ksi¹¿ce przyk³ady kodu maj¹ na celu zilustrowanie
                     O NOWO CIACH        przydatnych strategii programistycznych i ostrzec przed nabyciem niebezpiecznych
                                         nawyków. Aby dodatkowo u³atwiæ przyswajanie nowych umiejêtno ci, ka¿dy rozdzia³
                       ZAMÓW CENNIK      koñczy siê list¹ poruszonych w nim kluczowych zagadnieñ oraz pytaniami maj¹cymi
                                         spowodowaæ przemy lenia i dyskusje.
                                         Ksi¹¿ka przedstawia miêdzy innymi:
                 CZYTELNIA                  • Tworzenie w³a ciwych abstrakcji dla projektu i przekszta³canie abstrakcji
                                              w klasy C++
          FRAGMENTY KSI¥¯EK ONLINE          • Mechanizmy dziedziczenia pojedynczego i wielokrotnego
                                            • Metody tworzenia klas
                                            • Szczegó³owy opis mechanizmu szablonów
                                            • Wskazówki dotycz¹ce stosowania wyj¹tków
                                            • Metody tworzenia kodu nadaj¹cego siê do wielokrotnego wykorzystania
                                            • Przenoszenie programów z jêzyka C do C++
                                         Robert B. Murray jest wicedyrektorem ds. in¿ynierii oprogramowania w firmie
                                         Quantitative Data Systems dostarczaj¹cej niestandardowych rozwi¹zañ z zakresu
                                         oprogramowania dla czo³owych firm. Wcze nie pracowa³ w AT&T Bell Labs, gdzie bra³
                                         udzia³ w rozwoju jêzyka C++, jego kompilatorów i bibliotek. Jest pierwszym redaktorem
                                         magazynu „The C++ Report”. Od 1987 prowadzi zajêcia dotycz¹ce jêzyka C++ na
Wydawnictwo Helion                       konferencjach naukowych i technicznych.
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
5RKU VTG EK
             2TGFOQYC  
             9RTQYCFGPKG  
4QFKC    #DUVTCMELC  
             1.1. Abstrakcja numeru telefonu............................................................................................17
             1.2. Związki między abstrakcjami .........................................................................................19
             1.3. Problem warunków brzegowych ....................................................................................24
             1.4. Projektowanie z wykorzystaniem kart CRC ...................................................................25
             1.5. W skrócie ........................................................................................................................26
             1.6. Pytania ............................................................................................................................26
4QFKC    -NCU[  
             2.1. Konstruktory ...................................................................................................................27
             2.2. Przypisanie......................................................................................................................34
             2.3. Dane publiczne ...............................................................................................................36
             2.4. Niejawne konwersje typów.............................................................................................40
             2.5. Operatory przecią one — składowe czy nie?.................................................................44
             2.6. Przecią enie, argumenty domyślne i wielokropek .........................................................47
             2.7. Słowo kluczowe const ....................................................................................................48
             2.8. Zwracanie referencji .......................................................................................................54
             2.9. Konstruktory statyczne ...................................................................................................55
             2.10. W skrócie ......................................................................................................................56
             2.11. Pytania ..........................................................................................................................57
4QFKC    7EJY[V[ 
             3.1. Klasa Lancuch.................................................................................................................60
             3.2. Unikanie kopiowania przez zastosowanie liczników u ycia ..........................................61
             3.3. Zapobieganie powtórnym kompilacjom — „Kot z Cheshire”........................................66
             3.4. Stosowanie uchwytów w celu ukrycia szczegółów projektu..........................................68
             3.5. Implementacje wielokrotne.............................................................................................69
             3.6. Uchwyty jako obiekty .....................................................................................................72
             3.7. Podsumowanie ................................................................................................................73
             3.8. W skrócie ........................................................................................................................73
             3.9. Pytania ............................................................................................................................73
4QFKC    KGFKEGPKG 
             4.1. Związek generalizacji (specjalizacji)..............................................................................75
             4.2. Dziedziczenie publiczne .................................................................................................78
             4.3. Dziedziczenie prywatne ..................................................................................................78
             4.4. Dziedziczenie chronione.................................................................................................82
             4.5. Zgodność z abstrakcjami klasy bazowej.........................................................................83
             4.6. Funkcje czysto wirtualne ................................................................................................85
6       C++. Strategie i taktyki. Vademecum profesjonalisty


             4.7. Szczegóły i pułapki związane z dziedziczeniem ............................................................87
             4.8. W skrócie ........................................................................................................................90
             4.9. Pytania ............................................................................................................................90
4QFKC    KGFKEGPKG YKGNQMTQVPG  
             5.1. Dziedziczenie wielokrotne jako iloczyn zbiorów ...........................................................91
             5.2. Wirtualne klasy bazowe..................................................................................................96
             5.3. Pewne szczegóły dotyczące dziedziczenia wielokrotnego .............................................99
             5.4. W skrócie ......................................................................................................................101
             5.5. Pytania ..........................................................................................................................101
4QFKC    2TQLGMVQYCPKG RQF MæVGO FKGFKEGPKC 
             6.1. Interfejs chroniony ........................................................................................................103
             6.2. Czy nale y projektować pod kątem dziedziczenia?......................................................106
             6.3. Projektowanie pod kątem dziedziczenia — kilka przykładów .....................................111
             6.4. Podsumowanie ..............................................................................................................116
             6.5. W skrócie ......................................................................................................................116
             6.6. Pytania ..........................................................................................................................117
4QFKC    5CDNQP[ 
             7.1. Szablon klasy Para ........................................................................................................119
             7.2. Kilka szczegółów dotyczących szablonów...................................................................122
             7.3. Konkretyzacja szablonu ................................................................................................123
             7.4. Inteligentne wskaźniki ..................................................................................................125
             7.5. Argumenty wyra eniowe szablonów............................................................................131
             7.6. Szablony funkcji ...........................................................................................................132
             7.7. W skrócie ......................................................................................................................135
             7.8. Pytania ..........................................................................................................................136
4QFKC    5CDNQP[ CCYCPUQYCPG  
             8.1. Klasy kontenerowe wykorzystujące szablony ..............................................................139
             8.2. Przykład — klasa Blok .................................................................................................141
             8.3. Szczegóły projektowe klasy Blok.................................................................................143
             8.4. Kontenery z iteratorami — klasa Lista .........................................................................148
             8.5. Zagadnienia dotyczące projektowania iteratorów ........................................................154
             8.6. Zagadnienia dotyczące wydajności ..............................................................................157
             8.7. Ograniczenia dotyczące argumentów szablonów .........................................................160
             8.8. Specjalizacje szablonów ...............................................................................................162
             8.9. W skrócie ......................................................................................................................168
             8.10. Pytania ........................................................................................................................168
4QFKC    /Q NKYQ è RQPQYPGIQ Y[MQT[UVCPKC 
             9.1. Poznanie i nabycie ........................................................................................................172
             9.2. Odporność.....................................................................................................................173
             9.3. Zarządzanie pamięcią ...................................................................................................179
             9.4. Alternatywne metody alokacji pamięci ........................................................................181
             9.5. Przekazywanie argumentów do operatora new ............................................................184
             9.6. Zarządzanie zasobami zewnętrznymi ...........................................................................187
             9.7. Znajdowanie błędów pamięci .......................................................................................187
             9.8. Konflikty nazw .............................................................................................................192
             9.9. Wydajność ....................................................................................................................195
             9.10. Nie zgaduj — zmierz!.................................................................................................195
             9.11. Algorytmy ...................................................................................................................196
             9.12. Wąskie gardła w dynamicznej alokacji pamięci.........................................................197
             9.13. Funkcje rozwijane w miejscu wywołania ...................................................................202
Spis treści                     7


                   9.14. Prawo Tiemanna .........................................................................................................204
                   9.15. W skrócie ....................................................................................................................204
                   9.16. Pytania ........................................................................................................................205
4QFKC  9[LæVMK 
                   10.1. Sprostowanie...............................................................................................................209
                   10.2. Dlaczego wyjątki?.......................................................................................................209
                   10.3. Przykład wyjątku ........................................................................................................212
                   10.4. Wyjątki powinny być wyjątkowe ...............................................................................213
                   10.5. Zrozumieć wyjątki ......................................................................................................215
                   10.6. Oszacowanie winy ......................................................................................................215
                   10.7. Projektowanie obiektu wyjątku ..................................................................................217
                   10.8. W skrócie ....................................................................................................................219
                   10.9. Pytania ........................................................................................................................219
4QFKC  2TGPQUGPKG RTQLGMVÎY FQ %

  
                   11.1. Wybór języka C++......................................................................................................221
                   11.2. Przyswajanie C++ .......................................................................................................223
                   11.3. Projektowanie i implementacja...................................................................................224
                   11.4. Tworzenie bazy zasobów............................................................................................226
                   11.5. Uwagi końcowe ..........................................................................................................227
                   11.6. W skrócie ....................................................................................................................227
                   11.7. Pytania ........................................................................................................................228
                   5MQTQYKF
Rozdział 4.
KGFKEGPKG
       Wiele dyskusji dotyczących dziedziczenia rozpoczyna się od objaśnienia reguł języka.
       Chocia poznanie tych reguł jest niezbędne do korzystania z samego mechanizmu, to
       najpierw powinniśmy się upewnić, e rozumiemy, gdzie w projekcie dziedziczenie po-
       winno zostać zastosowane. Programy z nieodpowiednio zaprojektowanym dziedzicze-
       niem mo na wprawdzie doprowadzić do kompilacji, lecz będą one trudne do zrozumienia
       i utrzymania.


 YKæGM IGPGTCNKCELK 
URGELCNKCELK
       Dziedzicznie powinno zostać zastosowane w przypadku, gdy nowa klasa (klasa po-
       chodna) opisuje pewien zbiór obiektów, który jest podzbiorem obiektów opisywanych
       przez klasę bazową. Zale ność ta jest związkiem generalizacji (lub specjalizacji):
        ENCUU 2QLCF ]
        RWDNKE
            XKTVWCN FQWDNG RT[URKGU
FQWDNG
        _

        ENCUU 5COQNQV  RWDNKE 2QLCF ]
        RWDNKE
            XKTVWCN FQWDNG RT[URKGU
FQWDNG
        _

       Ka dy obiekt typu 5COQNQV jest równie obiektem typu 2QLCF (zauwa my, e relacja
       odwrotna nie jest prawdziwa — mogą istnieć obiekty typu 2QLCF, które nie są obiektami
       typu 5COQNQV). Ka da operacja, którą mo na zastosować do obiektu typu 2QLCF powinna
       równie mieć sens przy zastosowaniu do obiektu typu 5COQNQV (tj. funkcje składowe klasy
       bazowej mogą być wywoływane dla obiektów klasy pochodnej). W klasie pochodnej
       mo na zmienić implementację funkcji składowej przez przesłonięcie jej, lecz operacja
       pojęciowa powinna nadal mieć sens w klasie pochodnej. Ka dy pojazd mo na przyspie-
       szyć — rower będzie korzystał z innej implementacji tej operacji ni pociąg, lecz operacja
       pojęciowa będzie taka sama.


 KGFKEGPKG C  Q GPKG
       Dziedziczenie nie powinno być stosowane w przypadku, gdy klasa bazowa jest składni-
       kiem obiektu opisywanego przez klasę pochodną:
76     C++. Strategie i taktyki. Vademecum profesjonalisty


        ENCUU 5MT[FNQ ]
        RWDNKE
            FQWDNG FNWIQUE
 EQPUV
        _

        ENCUU 5COQNQV  RWDNKE 5MT[FNQ ]  0KGY C EKYG FKGFKEGPKG
         UEGIÎ [ RQOKPKúVQ
        _

       Obiekt typu 5COQNQV nie jest specjalnym rodzajem obiektu typu 5MT[FNQ, któremu
       przypadkiem doczepiono kadłub — 5COQNQV jest raczej obiektem zło onym z innych
       obiektów, w tym obiektu typu 5MT[FNQ (obiekt typu 5COQNQV nie jest obiektem typu
       5MT[FNQ, on ma 5MT[FNQ).

       Takie niewłaściwe u ycie mechanizmu dziedziczenia pozwala u ytkownikom stosować
       operacje klasy 5MT[FNQ do obiektu typu 5COQNQV:
        5COQNQV U
        FQWDNG F  UFNWIQUE


       W wyniku wywołania funkcji UFNWIQUE
zostanie zwrócona długość obiektu typu 5MT[
       FNQ, a nie obiektu typu 5COQNQV. Nie oznacza to wcale, e taki kod nie mo e działać, jest
       on jednak mylący — dlaczego skrzydło traktowane jest inaczej ni silnik czy śmigło?
       W jaki sposób skonstruować dwupłat — samolot o dwóch skrzydłach?

       W przypadku, gdy obiekt składa się z innych obiektów, właściwym podejściem będzie
       uczynienie tych obiektów składowymi, a nie klasami bazowymi:
        ENCUU 5COQNQV ]
            5MT[FNQ UM
            5OKINQ UO
         KVF
        _

       Oznacza to, e w operacjach na części 5MT[FNQ obiektu typu 5COQNQV trzeba będzie
       jawnie wymieniać składową UM typu 5MT[FNQ, lecz dzięki temu związek pomiędzy kla-
       sami 5COQNQV a 5MT[FNQ jest jaśniejszy — jest to związek ma (agregacji), a nie jest (ge-
       neralizacji).


 7UWYCPKG QRGTCELK Y MNCUKG RQEJQFPGL
       Ka da operacja występująca w bardziej ogólnej klasie bazowej powinna mieć zastosowanie
       do ka dego obiektu klasy pochodnej. Chocia w klasie pochodnej mo na zdefiniować
       nową implementację operacji przez przesłonięcie funkcji składowej klasy bazowej, to nie
       nale y próbować usunąć operacji, która jest dozwolona w klasie bazowej przez zadekla-
       rowanie jej jako prywatnej.

       Poni ej przedstawiamy przykład (wadliwej) hierarchii realizującej obiekty typu 2QLCF
       o dwóch rodzajach prędkości — prędkości normalnej, RTGFMQUE
, mierzonej względem
       podło a oraz prędkości lotu, RTGFMQUEANQVW
, mierzonej względem powietrza, która
       w obecności wiatru mo na być ró na od wartości RTGFMQUE
:
Rozdział 4.   Dziedziczenie       77


 ENCUU 2QLCF ]   [ RTQLGMV
 RWDNKE
     FQWDNG RTGFMQUE
 EQPUV
     FQWDNG RTGFMQUEANQVW
 EQPUV
 _

 ENCUU 2QLCFANCFQY[  RWDNKE 2QLCF ]
 RTKXCVG
      2QLCF[ NæFQYG PKG RQUKCFCLæ RTúFMQ EK NQVW
     FQWDNG RTGFMQUEANQVW
 EQPUV
 RWDNKE
      UEGIÎ [ RQOKPKúVQ
 _

Ponowna deklaracja składowej 2QLCFANCFQY[RTGFMQUEANQVW jako prywatnej stanowi próbę
uniemo liwienia wywołania funkcji RTGFMQUEANQVW dla obiektu typu 2QLCFANCFQY[:
 ENCUU 5COQEJQF  RWDNKE 2QLCFANCFQY[ ]
  UEGIÎ [ RQOKPKúVQ
 _

 2QLCFANCFQY[
RR  PGY 5COQEJQF
 FQWDNG NQV  RR RTGFMQUEANQVW
$ æF MQORKNCELK
                                      UM CFQYC RTGFMQUEANQVW LGUV RT[YCVPC
Próba ta jest jednak nieudana, poniewa zakazaną funkcję składową mo na mimo wszystko
wywołać poprzez wskaźnik typu 2QLCF
:
 2QLCF
RR  PGY 5COQEJQF
 FQWDNG NQV  RR RTGFMQUEANQVW
  QYQNQPG

Fakt podejmowania prób ograniczenia operacji w klasach pochodnych wskazuje zazwy-
czaj na to, e projekt hierarchii klas jest błędny. Aby rozwiązać ten problem w naszym
przykładzie, musimy rozstrzygnąć, czy mówienie o składowej RTGFMQUEANQVW
 pojazdu
lądowego ma w ogóle sens. Jeśli uznamy, e nie, to będzie znaczyło, e deklaracja funkcji
składowej RTGFMQUEANQVW
 nie powinna występować w adnej klasie, która jest klasą
bazową dla klasy 2QLCFANCFQY[. Zamiast tego, powinna zostać przeniesiona do takiego
miejsca w hierarchii klas, gdzie pytanie o prędkość lotu postawione wobec obiektów tej
klasy i wszystkich jej klas pochodnych będzie miało zawsze sens. W naszym przykła-
dzie powinniśmy utworzyć nową klasę 2QLCFARQYKGVTP[, z której będą wyprowadzane
wszystkie pojazdy posiadające prędkość lotu:
 ENCUU 2QLCF ]
 RWDNKE
     FQWDNG RTGFMQUE
 EQPUV
 _

 ENCUU 2QLCFANCFQY[  RWDNKE 2QLCF ]
_

 ENCUU 2QLCFARQYKGVTP[  RWDNKE 2QLCF ]
 RWDNKE
     FQWDNG RTGFMQUEANQVW
 EQPUV
      UEGIÎ [ RQOKPKúVQ
 _
78     C++. Strategie i taktyki. Vademecum profesjonalisty


       Przy takiej hierarchii klas nie mamy mo liwości wywołania funkcji RTGFMQUEANQVW wobec
       obiektu typu 2QLCFANCFQY[, nawet poprzez wskaźnik typu 2QLCF
(propozycję innego
       sposobu rozwiązania tego problemu zawiera pytanie 1 na końcu tego rozdziału).


 KGFKEGPKG RT[YCVPG EJTQPKQPG K RWDNKEPG
       Klasa określa dwa interfejsy dla świata zewnętrznego — jeden dla u ytkowników (skład-
       niki publiczne) oraz drugi dla implementatorów klas pochodnych (składniki chronione
       i prywatne). Mechanizm dziedziczenia działa w taki sam sposób: jeśli dziedziczenie jest
       publiczne, to wchodzi w skład interfejsu przeznaczonego dla u ytkowników, którzy
       mogą tym samym tworzyć kod zale ny od tego dziedziczenia. Jeśli dziedziczenie jest
       chronione, to jest jedynie częścią interfejsu przeznaczonego dla implementatorów klas
       pochodnych. Jeśli natomiast jest prywatne, to w ogóle nie wchodzi w skład interfejsu —
       mo e z niego korzystać jedynie implementator klasy (oraz klasy zaprzyjaźnione).


 KGFKEGPKG RWDNKEPG
       Dziedziczenie publiczne stosowane jest w przypadku, gdy dziedziczenie wchodzi w skład
       interfejsu, tj. pragniemy poinformować naszych u ytkowników o fakcie, e obiekt typu
       X jest obiektem typu Y (klasa X jest wyprowadzona z klasy Y). Podobnie jak w przy-
       padku wszystkich pozostałych elementów interfejsu, zobowiązujemy się (do pewnego
       stopnia) nigdy nie zmieniać tego elementu klasy! A to dlatego, e u ytkownicy mogą
       stworzyć kod uzale niony od niejawnej konwersji wskaźnika lub referencji do klasy 2Q
       EJQFPC na wskaźnik lub referencję do klasy $CQYC:
        XQKF WUVCYAMQNQT
-UVCNV  -QNQT
        -QNQ M
  MQ Q Q RTQOKGPKW 
        WUVCYAMQNQT
MPKGDKGUMK

       Powy szy kod opiera się na fakcie, e Koło jest Kształtem, a więc referencję do Koła
       M mo na przekazać do ka dej funkcji posiadającej parametr typu -UVCNV . Oznacza to,
         e nie mo emy w przyszłości zmodyfikować tej klasy, usuwając z niej dziedziczenie
       i oczekiwać, e istniejący ju kod będzie działał! Byłaby to niezgodna modyfikacja in-
       terfejsu — równowa na usunięciu publicznej funkcji składowej.


 KGFKEGPKG RT[YCVPG
       Dziedziczenie prywatne stosowane jest w przypadku, gdy dziedziczenie nie stanowi ele-
       mentu interfejsu, a jedynie implementacyjny szczegół. U ytkownicy nie mogą tworzyć
       kodu uzale nionego od takiego dziedziczenia, dzięki czemu zachowujemy mo liwość mo-
       dyfikacji implementacji polegającej na rezygnacji z u ywania danej klasy bazowej.

       Dziedziczenie prywatne stosowane jest znacznie rzadziej ni dziedziczenie publiczne,
       poniewa realizacja zło enia (czyli wykorzystanie części „klasy bazowej” jako danej
       składowej) jest prostsza i działa zazwyczaj równie dobrze. Zamiast dziedziczenia po
       klasie bazowej, pojedynczy obiekt tej klasy bazowej umieszczany jest jako składowa
       w klasie (dawnej) pochodnej. Takie rozwiązanie nie powinno powodować adnej utraty
Rozdział 4.   Dziedziczenie          79



Powtórka: Dziedziczenie publiczne, chronione i prywatne
W języku C++ istnieją trzy rodzaje dziedziczenia: RWDNKE, RTQVGEVGF oraz RTKXCVG. We wszystkich
formach dziedziczenia funkcje składowe klas pochodnych mają dostęp do składowych publicz-
nych i chronionych klasy bazowej — lecz nie do składowych prywatnych. Te trzy typy dziedziczenia
różnią się elementami, które są widoczne dla użytkownika klasy pochodnej (a nie twórcy klasy
pochodnej) oraz okolicznościami, w których użytkownik może niejawnie przekonwertować wskaź-
nik do klasy pochodnej na wskaźnik do klasy bazowej.
Najczęstszą formą dziedziczenia jest dziedziczenie publiczne:
   ENCUU -UVCNV ]
   RWDNKE
       -QNQT MQNQT

   _

   MNCUC -QNQ  RWDNKE -UVCNV ]
    UEGIÎ [ RQOKPKúVQ
   RWDNKE
       -QNQ
WPUKIPGF
       WPUKIPGF RTQOKGP 
 EQPUV
   _
Przy zastosowaniu dziedziczenia publicznego, składowe publiczne klasy bazowej pozostają pu-
bliczne w klasie pochodnej, a składowe chronione klasy bazowej pozostają chronione w klasie
pochodnej:
   -QNQ M
  WVYÎT MQ Q Q RTQOKGPKW 
   MMQNQT
  1-  HWPMELC MQNQT
 LGUV UM CFQYæ RWDNKEPæ
               RWDNKEPGL MNCU[ DCQYGL
Wskaźnik do klasy pochodnej może zostać niejawnie przekonwertowany na wskaźnik do publicznej
klasy bazowej:
   -UVCNV
MR  PGY -QNQ
  1-  -UVCNV LGUV RWDNKEPæ
                               MNCUæ DCQYæ
Przy zastosowaniu dziedziczenia prywatnego, składowe publiczne i chronione klasy bazowej stają
się prywatne w klasie pochodnej. Dostęp do nich mają składowe oraz funkcje i klasy zaprzyjaź-
nione klasy pochodnej, lecz nie użytkownicy:
   ENCUU .CPEWEJ ]
   RWDNKE
       .CPEWEJ
EQPUV EJCT
EJCT QRGTCVQT=?
KPV K EQPUV  KV[ PCM
       KPV FNWIQUE
 EQPUV
   _

   ENCUU 0WOGTAVGNGHQPW  RTKXCVG .CPEWEJ ]
   RWDNKE
       0WOGTAVGNGHQPW
EQPUV EJCT
KPV CYKGTCAMNCYKUGAURGELCNPG
 EQPUV
   _

Składowe klasy 0WOGTAVGNGHQPW mogą korzystać ze składowych publicznych i chronionych klasy
.CPEWEJ:
    KPENWFG EV[RGJ  HWPMELC KUFKIKV

   KPV
   0WOGTAVGNGHQPWCYKGTCAMNCYKUGAURGELCNPG
 EQPUV ]
80        C++. Strategie i taktyki. Vademecum profesjonalisty



     HQT 
KPV K   K  FNWIQUE
 

K
             KH 
 KUFKIKV

More Related Content

What's hot

C++. Zaawansowane programowanie
C++. Zaawansowane programowanieC++. Zaawansowane programowanie
C++. Zaawansowane programowanieWydawnictwo Helion
 
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykJęzyk C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykWydawnictwo Helion
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówWydawnictwo Helion
 
C++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIC++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIWydawnictwo Helion
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuWydawnictwo Helion
 
C++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyC++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyWydawnictwo Helion
 
Znajdź błąd. Sztuka analizowania kodu
Znajdź błąd. Sztuka analizowania koduZnajdź błąd. Sztuka analizowania kodu
Znajdź błąd. Sztuka analizowania koduWydawnictwo Helion
 
Visual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawVisual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawWydawnictwo Helion
 
C++Builder. Kompendium programisty
C++Builder. Kompendium programistyC++Builder. Kompendium programisty
C++Builder. Kompendium programistyWydawnictwo Helion
 

What's hot (20)

C++. Zaawansowane programowanie
C++. Zaawansowane programowanieC++. Zaawansowane programowanie
C++. Zaawansowane programowanie
 
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykJęzyk C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
 
Visual C# .NET. Encyklopedia
Visual C# .NET. EncyklopediaVisual C# .NET. Encyklopedia
Visual C# .NET. Encyklopedia
 
Uczta programistów
Uczta programistówUczta programistów
Uczta programistów
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistów
 
Język C. Programowanie
Język C. ProgramowanieJęzyk C. Programowanie
Język C. Programowanie
 
C++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIC++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie II
 
C++ bez obaw
C++ bez obawC++ bez obaw
C++ bez obaw
 
C++. Sztuka programowania
C++. Sztuka programowaniaC++. Sztuka programowania
C++. Sztuka programowania
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładu
 
C#. Wzorce projektowe
C#. Wzorce projektoweC#. Wzorce projektowe
C#. Wzorce projektowe
 
C# i .NET
C# i .NETC# i .NET
C# i .NET
 
C#. Ćwiczenia
C#. ĆwiczeniaC#. Ćwiczenia
C#. Ćwiczenia
 
C++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyC++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programisty
 
Programowanie. Od podstaw
Programowanie. Od podstawProgramowanie. Od podstaw
Programowanie. Od podstaw
 
C++. Leksykon kieszonkowy
C++. Leksykon kieszonkowyC++. Leksykon kieszonkowy
C++. Leksykon kieszonkowy
 
C++. Styl programowania
C++. Styl programowaniaC++. Styl programowania
C++. Styl programowania
 
Znajdź błąd. Sztuka analizowania kodu
Znajdź błąd. Sztuka analizowania koduZnajdź błąd. Sztuka analizowania kodu
Znajdź błąd. Sztuka analizowania kodu
 
Visual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawVisual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstaw
 
C++Builder. Kompendium programisty
C++Builder. Kompendium programistyC++Builder. Kompendium programisty
C++Builder. Kompendium programisty
 

Viewers also liked

The Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polskaThe Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polskaWydawnictwo Helion
 
Bezpieczeństwo w Linuksie. Podręcznik administratora
Bezpieczeństwo w Linuksie. Podręcznik administratoraBezpieczeństwo w Linuksie. Podręcznik administratora
Bezpieczeństwo w Linuksie. Podręcznik administratoraWydawnictwo Helion
 
Adobe After Effects 6.0. Oficjalny podręcznik
Adobe After Effects 6.0. Oficjalny podręcznikAdobe After Effects 6.0. Oficjalny podręcznik
Adobe After Effects 6.0. Oficjalny podręcznikWydawnictwo Helion
 
PC hardware. Almanach. Wydanie III
PC hardware. Almanach. Wydanie IIIPC hardware. Almanach. Wydanie III
PC hardware. Almanach. Wydanie IIIWydawnictwo Helion
 
STL w praktyce. 50 sposobów efektywnego wykorzystania
STL w praktyce. 50 sposobów efektywnego wykorzystaniaSTL w praktyce. 50 sposobów efektywnego wykorzystania
STL w praktyce. 50 sposobów efektywnego wykorzystaniaWydawnictwo Helion
 
Flash MX 2004. Skuteczne rozwiązania
Flash MX 2004. Skuteczne rozwiązaniaFlash MX 2004. Skuteczne rozwiązania
Flash MX 2004. Skuteczne rozwiązaniaWydawnictwo Helion
 
PowerPoint 2003 PL. Ćwiczenia
PowerPoint 2003 PL. ĆwiczeniaPowerPoint 2003 PL. Ćwiczenia
PowerPoint 2003 PL. ĆwiczeniaWydawnictwo Helion
 
INTERsoft IntelliCAD 4.0 PL. Pierwsze kroki
INTERsoft IntelliCAD 4.0 PL. Pierwsze krokiINTERsoft IntelliCAD 4.0 PL. Pierwsze kroki
INTERsoft IntelliCAD 4.0 PL. Pierwsze krokiWydawnictwo Helion
 

Viewers also liked (15)

Cisco. Receptury
Cisco. RecepturyCisco. Receptury
Cisco. Receptury
 
The Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polskaThe Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polska
 
Optymalizacja systemu Windows
Optymalizacja systemu WindowsOptymalizacja systemu Windows
Optymalizacja systemu Windows
 
Bezpieczeństwo w Linuksie. Podręcznik administratora
Bezpieczeństwo w Linuksie. Podręcznik administratoraBezpieczeństwo w Linuksie. Podręcznik administratora
Bezpieczeństwo w Linuksie. Podręcznik administratora
 
Contribute 2. Szybki start
Contribute 2. Szybki startContribute 2. Szybki start
Contribute 2. Szybki start
 
Adobe After Effects 6.0. Oficjalny podręcznik
Adobe After Effects 6.0. Oficjalny podręcznikAdobe After Effects 6.0. Oficjalny podręcznik
Adobe After Effects 6.0. Oficjalny podręcznik
 
Linux. Leksykon kieszonkowy
Linux. Leksykon kieszonkowyLinux. Leksykon kieszonkowy
Linux. Leksykon kieszonkowy
 
Red Hat Linux 9. Biblia
Red Hat Linux 9. BibliaRed Hat Linux 9. Biblia
Red Hat Linux 9. Biblia
 
Mandrake Linux
Mandrake LinuxMandrake Linux
Mandrake Linux
 
PC hardware. Almanach. Wydanie III
PC hardware. Almanach. Wydanie IIIPC hardware. Almanach. Wydanie III
PC hardware. Almanach. Wydanie III
 
STL w praktyce. 50 sposobów efektywnego wykorzystania
STL w praktyce. 50 sposobów efektywnego wykorzystaniaSTL w praktyce. 50 sposobów efektywnego wykorzystania
STL w praktyce. 50 sposobów efektywnego wykorzystania
 
Flash MX 2004. Skuteczne rozwiązania
Flash MX 2004. Skuteczne rozwiązaniaFlash MX 2004. Skuteczne rozwiązania
Flash MX 2004. Skuteczne rozwiązania
 
PowerPoint 2003 PL. Ćwiczenia
PowerPoint 2003 PL. ĆwiczeniaPowerPoint 2003 PL. Ćwiczenia
PowerPoint 2003 PL. Ćwiczenia
 
INTERsoft IntelliCAD 4.0 PL. Pierwsze kroki
INTERsoft IntelliCAD 4.0 PL. Pierwsze krokiINTERsoft IntelliCAD 4.0 PL. Pierwsze kroki
INTERsoft IntelliCAD 4.0 PL. Pierwsze kroki
 
Złóż własny komputer
Złóż własny komputerZłóż własny komputer
Złóż własny komputer
 

Similar to C++. Strategie i taktyki. Vademecum profesjonalisty

Programowanie w języku C. FAQ
Programowanie w języku C. FAQProgramowanie w języku C. FAQ
Programowanie w języku C. FAQWydawnictwo Helion
 
Język C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalistyJęzyk C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalistyWydawnictwo Helion
 
Więcej niż architektura oprogramowania
Więcej niż architektura oprogramowaniaWięcej niż architektura oprogramowania
Więcej niż architektura oprogramowaniaWydawnictwo Helion
 
Aplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyAplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyWydawnictwo Helion
 
Algorytmy, struktury danych i techniki programowania. Wydanie III
Algorytmy, struktury danych i techniki programowania. Wydanie IIIAlgorytmy, struktury danych i techniki programowania. Wydanie III
Algorytmy, struktury danych i techniki programowania. Wydanie IIIWydawnictwo Helion
 
Projektowanie oprogramowania. Wstęp do programowania i techniki komputerowej
Projektowanie oprogramowania. Wstęp do programowania i techniki komputerowejProjektowanie oprogramowania. Wstęp do programowania i techniki komputerowej
Projektowanie oprogramowania. Wstęp do programowania i techniki komputerowejWydawnictwo Helion
 
Profesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerProfesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerWydawnictwo Helion
 
C++. Algorytmy i struktury danych
C++. Algorytmy i struktury danychC++. Algorytmy i struktury danych
C++. Algorytmy i struktury danychWydawnictwo Helion
 
J2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnychJ2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnychWydawnictwo Helion
 
Programowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modeleProgramowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modeleWydawnictwo Helion
 

Similar to C++. Strategie i taktyki. Vademecum profesjonalisty (13)

Programowanie w języku C. FAQ
Programowanie w języku C. FAQProgramowanie w języku C. FAQ
Programowanie w języku C. FAQ
 
Język C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalistyJęzyk C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalisty
 
Więcej niż architektura oprogramowania
Więcej niż architektura oprogramowaniaWięcej niż architektura oprogramowania
Więcej niż architektura oprogramowania
 
C++BuilderX. Ćwiczenia
C++BuilderX. ĆwiczeniaC++BuilderX. Ćwiczenia
C++BuilderX. Ćwiczenia
 
Aplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyAplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. Przykłady
 
C++Builder 6 i bazy danych
C++Builder 6 i bazy danychC++Builder 6 i bazy danych
C++Builder 6 i bazy danych
 
C# i ASP.NET. Szybki start
C# i ASP.NET. Szybki startC# i ASP.NET. Szybki start
C# i ASP.NET. Szybki start
 
Algorytmy, struktury danych i techniki programowania. Wydanie III
Algorytmy, struktury danych i techniki programowania. Wydanie IIIAlgorytmy, struktury danych i techniki programowania. Wydanie III
Algorytmy, struktury danych i techniki programowania. Wydanie III
 
Projektowanie oprogramowania. Wstęp do programowania i techniki komputerowej
Projektowanie oprogramowania. Wstęp do programowania i techniki komputerowejProjektowanie oprogramowania. Wstęp do programowania i techniki komputerowej
Projektowanie oprogramowania. Wstęp do programowania i techniki komputerowej
 
Profesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerProfesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputer
 
C++. Algorytmy i struktury danych
C++. Algorytmy i struktury danychC++. Algorytmy i struktury danych
C++. Algorytmy i struktury danych
 
J2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnychJ2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnych
 
Programowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modeleProgramowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modele
 

More from Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 

More from Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 

C++. Strategie i taktyki. Vademecum profesjonalisty

  • 1. IDZ DO PRZYK£ADOWY ROZDZIA£ SPIS TRE CI C++. Strategie i taktyki. Vademecum profesjonalisty KATALOG KSI¥¯EK Autor: Robert B. Murray KATALOG ONLINE T³umaczenie: Przemys³aw Steæ ISBN: 83-7361-323-4 ZAMÓW DRUKOWANY KATALOG Tytu³ orygina³u: C++ Strategies and Tactics Format: B5, stron: 240 TWÓJ KOSZYK DODAJ DO KOSZYKA Poznanie ruchów figur szachowych to dopiero pierwszy krok w nauce tej gry. Aby j¹ opanowaæ, trzeba zrozumieæ strategie i taktyki, które wp³ywaj¹ na ka¿dy ruch. To samo dotyczy jêzyka C++. Znajomo æ w³a ciwych strategii pomaga unikaæ pu³apek CENNIK I INFORMACJE i pracowaæ o wiele skuteczniej. Rob Murray dziel¹c siê swoim do wiadczeniem pomaga programistom C++ wykonaæ nastêpny krok w kierunku tworzenia wydajnych aplikacji. ZAMÓW INFORMACJE Licznie wystêpuj¹ce w ca³ej ksi¹¿ce przyk³ady kodu maj¹ na celu zilustrowanie O NOWO CIACH przydatnych strategii programistycznych i ostrzec przed nabyciem niebezpiecznych nawyków. Aby dodatkowo u³atwiæ przyswajanie nowych umiejêtno ci, ka¿dy rozdzia³ ZAMÓW CENNIK koñczy siê list¹ poruszonych w nim kluczowych zagadnieñ oraz pytaniami maj¹cymi spowodowaæ przemy lenia i dyskusje. Ksi¹¿ka przedstawia miêdzy innymi: CZYTELNIA • Tworzenie w³a ciwych abstrakcji dla projektu i przekszta³canie abstrakcji w klasy C++ FRAGMENTY KSI¥¯EK ONLINE • Mechanizmy dziedziczenia pojedynczego i wielokrotnego • Metody tworzenia klas • Szczegó³owy opis mechanizmu szablonów • Wskazówki dotycz¹ce stosowania wyj¹tków • Metody tworzenia kodu nadaj¹cego siê do wielokrotnego wykorzystania • Przenoszenie programów z jêzyka C do C++ Robert B. Murray jest wicedyrektorem ds. in¿ynierii oprogramowania w firmie Quantitative Data Systems dostarczaj¹cej niestandardowych rozwi¹zañ z zakresu oprogramowania dla czo³owych firm. Wcze nie pracowa³ w AT&T Bell Labs, gdzie bra³ udzia³ w rozwoju jêzyka C++, jego kompilatorów i bibliotek. Jest pierwszym redaktorem magazynu „The C++ Report”. Od 1987 prowadzi zajêcia dotycz¹ce jêzyka C++ na Wydawnictwo Helion konferencjach naukowych i technicznych. ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: helion@helion.pl
  • 2. 5RKU VTG EK 2TGFOQYC 9RTQYCFGPKG 4QFKC #DUVTCMELC 1.1. Abstrakcja numeru telefonu............................................................................................17 1.2. Związki między abstrakcjami .........................................................................................19 1.3. Problem warunków brzegowych ....................................................................................24 1.4. Projektowanie z wykorzystaniem kart CRC ...................................................................25 1.5. W skrócie ........................................................................................................................26 1.6. Pytania ............................................................................................................................26 4QFKC -NCU[ 2.1. Konstruktory ...................................................................................................................27 2.2. Przypisanie......................................................................................................................34 2.3. Dane publiczne ...............................................................................................................36 2.4. Niejawne konwersje typów.............................................................................................40 2.5. Operatory przecią one — składowe czy nie?.................................................................44 2.6. Przecią enie, argumenty domyślne i wielokropek .........................................................47 2.7. Słowo kluczowe const ....................................................................................................48 2.8. Zwracanie referencji .......................................................................................................54 2.9. Konstruktory statyczne ...................................................................................................55 2.10. W skrócie ......................................................................................................................56 2.11. Pytania ..........................................................................................................................57 4QFKC 7EJY[V[ 3.1. Klasa Lancuch.................................................................................................................60 3.2. Unikanie kopiowania przez zastosowanie liczników u ycia ..........................................61 3.3. Zapobieganie powtórnym kompilacjom — „Kot z Cheshire”........................................66 3.4. Stosowanie uchwytów w celu ukrycia szczegółów projektu..........................................68 3.5. Implementacje wielokrotne.............................................................................................69 3.6. Uchwyty jako obiekty .....................................................................................................72 3.7. Podsumowanie ................................................................................................................73 3.8. W skrócie ........................................................................................................................73 3.9. Pytania ............................................................................................................................73 4QFKC KGFKEGPKG 4.1. Związek generalizacji (specjalizacji)..............................................................................75 4.2. Dziedziczenie publiczne .................................................................................................78 4.3. Dziedziczenie prywatne ..................................................................................................78 4.4. Dziedziczenie chronione.................................................................................................82 4.5. Zgodność z abstrakcjami klasy bazowej.........................................................................83 4.6. Funkcje czysto wirtualne ................................................................................................85
  • 3. 6 C++. Strategie i taktyki. Vademecum profesjonalisty 4.7. Szczegóły i pułapki związane z dziedziczeniem ............................................................87 4.8. W skrócie ........................................................................................................................90 4.9. Pytania ............................................................................................................................90 4QFKC KGFKEGPKG YKGNQMTQVPG 5.1. Dziedziczenie wielokrotne jako iloczyn zbiorów ...........................................................91 5.2. Wirtualne klasy bazowe..................................................................................................96 5.3. Pewne szczegóły dotyczące dziedziczenia wielokrotnego .............................................99 5.4. W skrócie ......................................................................................................................101 5.5. Pytania ..........................................................................................................................101 4QFKC 2TQLGMVQYCPKG RQF MæVGO FKGFKEGPKC 6.1. Interfejs chroniony ........................................................................................................103 6.2. Czy nale y projektować pod kątem dziedziczenia?......................................................106 6.3. Projektowanie pod kątem dziedziczenia — kilka przykładów .....................................111 6.4. Podsumowanie ..............................................................................................................116 6.5. W skrócie ......................................................................................................................116 6.6. Pytania ..........................................................................................................................117 4QFKC 5CDNQP[ 7.1. Szablon klasy Para ........................................................................................................119 7.2. Kilka szczegółów dotyczących szablonów...................................................................122 7.3. Konkretyzacja szablonu ................................................................................................123 7.4. Inteligentne wskaźniki ..................................................................................................125 7.5. Argumenty wyra eniowe szablonów............................................................................131 7.6. Szablony funkcji ...........................................................................................................132 7.7. W skrócie ......................................................................................................................135 7.8. Pytania ..........................................................................................................................136 4QFKC 5CDNQP[ CCYCPUQYCPG 8.1. Klasy kontenerowe wykorzystujące szablony ..............................................................139 8.2. Przykład — klasa Blok .................................................................................................141 8.3. Szczegóły projektowe klasy Blok.................................................................................143 8.4. Kontenery z iteratorami — klasa Lista .........................................................................148 8.5. Zagadnienia dotyczące projektowania iteratorów ........................................................154 8.6. Zagadnienia dotyczące wydajności ..............................................................................157 8.7. Ograniczenia dotyczące argumentów szablonów .........................................................160 8.8. Specjalizacje szablonów ...............................................................................................162 8.9. W skrócie ......................................................................................................................168 8.10. Pytania ........................................................................................................................168 4QFKC /Q NKYQ è RQPQYPGIQ Y[MQT[UVCPKC 9.1. Poznanie i nabycie ........................................................................................................172 9.2. Odporność.....................................................................................................................173 9.3. Zarządzanie pamięcią ...................................................................................................179 9.4. Alternatywne metody alokacji pamięci ........................................................................181 9.5. Przekazywanie argumentów do operatora new ............................................................184 9.6. Zarządzanie zasobami zewnętrznymi ...........................................................................187 9.7. Znajdowanie błędów pamięci .......................................................................................187 9.8. Konflikty nazw .............................................................................................................192 9.9. Wydajność ....................................................................................................................195 9.10. Nie zgaduj — zmierz!.................................................................................................195 9.11. Algorytmy ...................................................................................................................196 9.12. Wąskie gardła w dynamicznej alokacji pamięci.........................................................197 9.13. Funkcje rozwijane w miejscu wywołania ...................................................................202
  • 4. Spis treści 7 9.14. Prawo Tiemanna .........................................................................................................204 9.15. W skrócie ....................................................................................................................204 9.16. Pytania ........................................................................................................................205 4QFKC 9[LæVMK 10.1. Sprostowanie...............................................................................................................209 10.2. Dlaczego wyjątki?.......................................................................................................209 10.3. Przykład wyjątku ........................................................................................................212 10.4. Wyjątki powinny być wyjątkowe ...............................................................................213 10.5. Zrozumieć wyjątki ......................................................................................................215 10.6. Oszacowanie winy ......................................................................................................215 10.7. Projektowanie obiektu wyjątku ..................................................................................217 10.8. W skrócie ....................................................................................................................219 10.9. Pytania ........................................................................................................................219 4QFKC 2TGPQUGPKG RTQLGMVÎY FQ % 11.1. Wybór języka C++......................................................................................................221 11.2. Przyswajanie C++ .......................................................................................................223 11.3. Projektowanie i implementacja...................................................................................224 11.4. Tworzenie bazy zasobów............................................................................................226 11.5. Uwagi końcowe ..........................................................................................................227 11.6. W skrócie ....................................................................................................................227 11.7. Pytania ........................................................................................................................228 5MQTQYKF
  • 5. Rozdział 4. KGFKEGPKG Wiele dyskusji dotyczących dziedziczenia rozpoczyna się od objaśnienia reguł języka. Chocia poznanie tych reguł jest niezbędne do korzystania z samego mechanizmu, to najpierw powinniśmy się upewnić, e rozumiemy, gdzie w projekcie dziedziczenie po- winno zostać zastosowane. Programy z nieodpowiednio zaprojektowanym dziedzicze- niem mo na wprawdzie doprowadzić do kompilacji, lecz będą one trudne do zrozumienia i utrzymania. YKæGM IGPGTCNKCELK URGELCNKCELK Dziedzicznie powinno zostać zastosowane w przypadku, gdy nowa klasa (klasa po- chodna) opisuje pewien zbiór obiektów, który jest podzbiorem obiektów opisywanych przez klasę bazową. Zale ność ta jest związkiem generalizacji (lub specjalizacji): ENCUU 2QLCF ] RWDNKE XKTVWCN FQWDNG RT[URKGU FQWDNG _ ENCUU 5COQNQV RWDNKE 2QLCF ] RWDNKE XKTVWCN FQWDNG RT[URKGU FQWDNG _ Ka dy obiekt typu 5COQNQV jest równie obiektem typu 2QLCF (zauwa my, e relacja odwrotna nie jest prawdziwa — mogą istnieć obiekty typu 2QLCF, które nie są obiektami typu 5COQNQV). Ka da operacja, którą mo na zastosować do obiektu typu 2QLCF powinna równie mieć sens przy zastosowaniu do obiektu typu 5COQNQV (tj. funkcje składowe klasy bazowej mogą być wywoływane dla obiektów klasy pochodnej). W klasie pochodnej mo na zmienić implementację funkcji składowej przez przesłonięcie jej, lecz operacja pojęciowa powinna nadal mieć sens w klasie pochodnej. Ka dy pojazd mo na przyspie- szyć — rower będzie korzystał z innej implementacji tej operacji ni pociąg, lecz operacja pojęciowa będzie taka sama. KGFKEGPKG C Q GPKG Dziedziczenie nie powinno być stosowane w przypadku, gdy klasa bazowa jest składni- kiem obiektu opisywanego przez klasę pochodną:
  • 6. 76 C++. Strategie i taktyki. Vademecum profesjonalisty ENCUU 5MT[FNQ ] RWDNKE FQWDNG FNWIQUE EQPUV _ ENCUU 5COQNQV RWDNKE 5MT[FNQ ] 0KGY C EKYG FKGFKEGPKG UEGIÎ [ RQOKPKúVQ _ Obiekt typu 5COQNQV nie jest specjalnym rodzajem obiektu typu 5MT[FNQ, któremu przypadkiem doczepiono kadłub — 5COQNQV jest raczej obiektem zło onym z innych obiektów, w tym obiektu typu 5MT[FNQ (obiekt typu 5COQNQV nie jest obiektem typu 5MT[FNQ, on ma 5MT[FNQ). Takie niewłaściwe u ycie mechanizmu dziedziczenia pozwala u ytkownikom stosować operacje klasy 5MT[FNQ do obiektu typu 5COQNQV: 5COQNQV U FQWDNG F UFNWIQUE W wyniku wywołania funkcji UFNWIQUE zostanie zwrócona długość obiektu typu 5MT[ FNQ, a nie obiektu typu 5COQNQV. Nie oznacza to wcale, e taki kod nie mo e działać, jest on jednak mylący — dlaczego skrzydło traktowane jest inaczej ni silnik czy śmigło? W jaki sposób skonstruować dwupłat — samolot o dwóch skrzydłach? W przypadku, gdy obiekt składa się z innych obiektów, właściwym podejściem będzie uczynienie tych obiektów składowymi, a nie klasami bazowymi: ENCUU 5COQNQV ] 5MT[FNQ UM 5OKINQ UO KVF _ Oznacza to, e w operacjach na części 5MT[FNQ obiektu typu 5COQNQV trzeba będzie jawnie wymieniać składową UM typu 5MT[FNQ, lecz dzięki temu związek pomiędzy kla- sami 5COQNQV a 5MT[FNQ jest jaśniejszy — jest to związek ma (agregacji), a nie jest (ge- neralizacji). 7UWYCPKG QRGTCELK Y MNCUKG RQEJQFPGL Ka da operacja występująca w bardziej ogólnej klasie bazowej powinna mieć zastosowanie do ka dego obiektu klasy pochodnej. Chocia w klasie pochodnej mo na zdefiniować nową implementację operacji przez przesłonięcie funkcji składowej klasy bazowej, to nie nale y próbować usunąć operacji, która jest dozwolona w klasie bazowej przez zadekla- rowanie jej jako prywatnej. Poni ej przedstawiamy przykład (wadliwej) hierarchii realizującej obiekty typu 2QLCF o dwóch rodzajach prędkości — prędkości normalnej, RTGFMQUE , mierzonej względem podło a oraz prędkości lotu, RTGFMQUEANQVW , mierzonej względem powietrza, która w obecności wiatru mo na być ró na od wartości RTGFMQUE :
  • 7. Rozdział 4. Dziedziczenie 77 ENCUU 2QLCF ] [ RTQLGMV RWDNKE FQWDNG RTGFMQUE EQPUV FQWDNG RTGFMQUEANQVW EQPUV _ ENCUU 2QLCFANCFQY[ RWDNKE 2QLCF ] RTKXCVG 2QLCF[ NæFQYG PKG RQUKCFCLæ RTúFMQ EK NQVW FQWDNG RTGFMQUEANQVW EQPUV RWDNKE UEGIÎ [ RQOKPKúVQ _ Ponowna deklaracja składowej 2QLCFANCFQY[RTGFMQUEANQVW jako prywatnej stanowi próbę uniemo liwienia wywołania funkcji RTGFMQUEANQVW dla obiektu typu 2QLCFANCFQY[: ENCUU 5COQEJQF RWDNKE 2QLCFANCFQY[ ] UEGIÎ [ RQOKPKúVQ _ 2QLCFANCFQY[
  • 8. RR PGY 5COQEJQF FQWDNG NQV RR RTGFMQUEANQVW
  • 9. $ æF MQORKNCELK UM CFQYC RTGFMQUEANQVW LGUV RT[YCVPC
  • 10. Próba ta jest jednak nieudana, poniewa zakazaną funkcję składową mo na mimo wszystko wywołać poprzez wskaźnik typu 2QLCF
  • 12. RR PGY 5COQEJQF FQWDNG NQV RR RTGFMQUEANQVW QYQNQPG Fakt podejmowania prób ograniczenia operacji w klasach pochodnych wskazuje zazwy- czaj na to, e projekt hierarchii klas jest błędny. Aby rozwiązać ten problem w naszym przykładzie, musimy rozstrzygnąć, czy mówienie o składowej RTGFMQUEANQVW pojazdu lądowego ma w ogóle sens. Jeśli uznamy, e nie, to będzie znaczyło, e deklaracja funkcji składowej RTGFMQUEANQVW nie powinna występować w adnej klasie, która jest klasą bazową dla klasy 2QLCFANCFQY[. Zamiast tego, powinna zostać przeniesiona do takiego miejsca w hierarchii klas, gdzie pytanie o prędkość lotu postawione wobec obiektów tej klasy i wszystkich jej klas pochodnych będzie miało zawsze sens. W naszym przykła- dzie powinniśmy utworzyć nową klasę 2QLCFARQYKGVTP[, z której będą wyprowadzane wszystkie pojazdy posiadające prędkość lotu: ENCUU 2QLCF ] RWDNKE FQWDNG RTGFMQUE EQPUV _ ENCUU 2QLCFANCFQY[ RWDNKE 2QLCF ]
  • 13. _ ENCUU 2QLCFARQYKGVTP[ RWDNKE 2QLCF ] RWDNKE FQWDNG RTGFMQUEANQVW EQPUV UEGIÎ [ RQOKPKúVQ _
  • 14. 78 C++. Strategie i taktyki. Vademecum profesjonalisty Przy takiej hierarchii klas nie mamy mo liwości wywołania funkcji RTGFMQUEANQVW wobec obiektu typu 2QLCFANCFQY[, nawet poprzez wskaźnik typu 2QLCF
  • 15. (propozycję innego sposobu rozwiązania tego problemu zawiera pytanie 1 na końcu tego rozdziału). KGFKEGPKG RT[YCVPG EJTQPKQPG K RWDNKEPG Klasa określa dwa interfejsy dla świata zewnętrznego — jeden dla u ytkowników (skład- niki publiczne) oraz drugi dla implementatorów klas pochodnych (składniki chronione i prywatne). Mechanizm dziedziczenia działa w taki sam sposób: jeśli dziedziczenie jest publiczne, to wchodzi w skład interfejsu przeznaczonego dla u ytkowników, którzy mogą tym samym tworzyć kod zale ny od tego dziedziczenia. Jeśli dziedziczenie jest chronione, to jest jedynie częścią interfejsu przeznaczonego dla implementatorów klas pochodnych. Jeśli natomiast jest prywatne, to w ogóle nie wchodzi w skład interfejsu — mo e z niego korzystać jedynie implementator klasy (oraz klasy zaprzyjaźnione). KGFKEGPKG RWDNKEPG Dziedziczenie publiczne stosowane jest w przypadku, gdy dziedziczenie wchodzi w skład interfejsu, tj. pragniemy poinformować naszych u ytkowników o fakcie, e obiekt typu X jest obiektem typu Y (klasa X jest wyprowadzona z klasy Y). Podobnie jak w przy- padku wszystkich pozostałych elementów interfejsu, zobowiązujemy się (do pewnego stopnia) nigdy nie zmieniać tego elementu klasy! A to dlatego, e u ytkownicy mogą stworzyć kod uzale niony od niejawnej konwersji wskaźnika lub referencji do klasy 2Q EJQFPC na wskaźnik lub referencję do klasy $CQYC: XQKF WUVCYAMQNQT -UVCNV -QNQT -QNQ M MQ Q Q RTQOKGPKW WUVCYAMQNQT MPKGDKGUMK Powy szy kod opiera się na fakcie, e Koło jest Kształtem, a więc referencję do Koła M mo na przekazać do ka dej funkcji posiadającej parametr typu -UVCNV . Oznacza to, e nie mo emy w przyszłości zmodyfikować tej klasy, usuwając z niej dziedziczenie i oczekiwać, e istniejący ju kod będzie działał! Byłaby to niezgodna modyfikacja in- terfejsu — równowa na usunięciu publicznej funkcji składowej. KGFKEGPKG RT[YCVPG Dziedziczenie prywatne stosowane jest w przypadku, gdy dziedziczenie nie stanowi ele- mentu interfejsu, a jedynie implementacyjny szczegół. U ytkownicy nie mogą tworzyć kodu uzale nionego od takiego dziedziczenia, dzięki czemu zachowujemy mo liwość mo- dyfikacji implementacji polegającej na rezygnacji z u ywania danej klasy bazowej. Dziedziczenie prywatne stosowane jest znacznie rzadziej ni dziedziczenie publiczne, poniewa realizacja zło enia (czyli wykorzystanie części „klasy bazowej” jako danej składowej) jest prostsza i działa zazwyczaj równie dobrze. Zamiast dziedziczenia po klasie bazowej, pojedynczy obiekt tej klasy bazowej umieszczany jest jako składowa w klasie (dawnej) pochodnej. Takie rozwiązanie nie powinno powodować adnej utraty
  • 16. Rozdział 4. Dziedziczenie 79 Powtórka: Dziedziczenie publiczne, chronione i prywatne W języku C++ istnieją trzy rodzaje dziedziczenia: RWDNKE, RTQVGEVGF oraz RTKXCVG. We wszystkich formach dziedziczenia funkcje składowe klas pochodnych mają dostęp do składowych publicz- nych i chronionych klasy bazowej — lecz nie do składowych prywatnych. Te trzy typy dziedziczenia różnią się elementami, które są widoczne dla użytkownika klasy pochodnej (a nie twórcy klasy pochodnej) oraz okolicznościami, w których użytkownik może niejawnie przekonwertować wskaź- nik do klasy pochodnej na wskaźnik do klasy bazowej. Najczęstszą formą dziedziczenia jest dziedziczenie publiczne: ENCUU -UVCNV ] RWDNKE -QNQT MQNQT _ MNCUC -QNQ RWDNKE -UVCNV ] UEGIÎ [ RQOKPKúVQ RWDNKE -QNQ WPUKIPGF WPUKIPGF RTQOKGP EQPUV _ Przy zastosowaniu dziedziczenia publicznego, składowe publiczne klasy bazowej pozostają pu- bliczne w klasie pochodnej, a składowe chronione klasy bazowej pozostają chronione w klasie pochodnej: -QNQ M WVYÎT MQ Q Q RTQOKGPKW MMQNQT 1- HWPMELC MQNQT LGUV UM CFQYæ RWDNKEPæ RWDNKEPGL MNCU[ DCQYGL Wskaźnik do klasy pochodnej może zostać niejawnie przekonwertowany na wskaźnik do publicznej klasy bazowej: -UVCNV
  • 17. MR PGY -QNQ 1- -UVCNV LGUV RWDNKEPæ MNCUæ DCQYæ Przy zastosowaniu dziedziczenia prywatnego, składowe publiczne i chronione klasy bazowej stają się prywatne w klasie pochodnej. Dostęp do nich mają składowe oraz funkcje i klasy zaprzyjaź- nione klasy pochodnej, lecz nie użytkownicy: ENCUU .CPEWEJ ] RWDNKE .CPEWEJ EQPUV EJCT
  • 18. EJCT QRGTCVQT=? KPV K EQPUV KV[ PCM KPV FNWIQUE EQPUV _ ENCUU 0WOGTAVGNGHQPW RTKXCVG .CPEWEJ ] RWDNKE 0WOGTAVGNGHQPW EQPUV EJCT
  • 19. KPV CYKGTCAMNCYKUGAURGELCNPG EQPUV _ Składowe klasy 0WOGTAVGNGHQPW mogą korzystać ze składowych publicznych i chronionych klasy .CPEWEJ: KPENWFG EV[RGJ HWPMELC KUFKIKV KPV 0WOGTAVGNGHQPWCYKGTCAMNCYKUGAURGELCNPG EQPUV ]
  • 20. 80 C++. Strategie i taktyki. Vademecum profesjonalisty HQT KPV K K FNWIQUE K KH KUFKIKV
  • 21. VJKU=K? TGVWTP TGVWTP _ Użytkownicy klasy 0WOGTAVGNGHQPW nie mogą jednak wywoływać żadnych składowych klasy .CPEWEJ: OCKP ] 0WOGTAVGNGHQPW PV KPV FNWI PVFNWIQUE $ æF MQORKNCELK UM CFQYC FNWIQUE LGUV RT[YCVPC Użytkownicy nie mogą również wykonać niejawnej konwersji wskaźnika do klasy pochodnej na wskaźnik do klasy bazowej: XQKF H ] 0WOGTAVGNGHQPW U .CPEWEJ
  • 22. YUM U $ æF MQORKNCELK .CPEWEJ LGUV RT[YCVPæ MNCUæ DCQYæ _ Przy zastosowaniu dziedziczenia prywatnego, składowe publiczne i chronione klasy bazowej stają się chronione w klasie pochodnej. Klasy pochodne mogą wywoływać funkcje składowe chronio- nej klasy bazowej, a także niejawnie przekonwertować wskaźnik do klasy pochodnej na wskaźnik do chronionej klasy bazowej. Składową publiczną prywatnej lub chronionej klasy bazowej można uczynić publiczną w klasie po- chodnej za pomocą tzw. deklaracji dostępu: ENCUU .CPEWEJ ] RWDNKE KPV FNWIQUE EQPUV _ ENCUU 0WOGTAVGNGHQPW RTKXCVG .CPEWEJ ] RWDNKE .CPEWEJFNWIQUE GMNCTCELC FQUVúRW _ Dzięki temu użytkownicy będą mieli możliwość wywoływania dla obiektu typu 0WOGTAVGNGHQPW funkcji FNWIQUE tak, jak gdyby została ona zadeklarowana w następujący sposób: ENCUU 0WOGTAVGNGHQPW RTKXCVG .CPEWEJ ] RWDNKE KPV FNWIQUE ] TGVWTP .CPEWEJFNWIQUE _ _ wydajności ani wymagać dodatkowego obszaru pamięci, a powstała w ten sposób klasa będzie łatwiejsza do zrozumienia, poniewa czytając kod nie będzie trzeba pamiętać, które funkcje składowe dziedziczone są po prywatnej klasie bazowej. Implementacja przykładowej klasy 0WOGTAVGNGHQPW zaprezentowanej w ramce „Powtórka: Dziedziczenie publiczne, chronione i prywatne” powinna zostać zmodyfikowana w na- stępujący sposób:
  • 23. Rozdział 4. Dziedziczenie 81 KPENWFG EV[RGJ HWPMELC KUFKIKV ENCUU .CPEWEJ ] 6CM LCM YEG PKGL DG OKCP RWDNKE .CPEWEJ EQPUV EJCT
  • 24. EJCT QRGTCVQT=? KPV K EQPUV KV[ PCM KPV FNWIQUE EQPUV _ ENCUU 0WOGTAVGNGHQPW] RTKXCVG .CPEWEJ U RWDNKE 0WOGTAVGNGHQPW EQPUV EJCT
  • 25. KPV CYKGTCAMNCYKUGAURGELCNPG EQPUV _ KPV 0WOGTAVGNGHQPWCYKGTCAMNCYKUGAURGELCNPG EQPUV ] HQT KPV K K UFNWIQUE K KH KUFKIKV U=K? TGVWTP TGVWTP _ Jedyne zmiany w treści kodu funkcji składowych klasy 0WOGTAVGNGHQPW wynikają z ko- nieczności uściślenia niejawnych odwołań do składowych klasy bazowej .CPEWEJ nazwą składowej U typu .CPEWEJ. Zmiana ta jest niewidoczna dla u ytkowników — ich kod będzie działał jak dotąd. Mało prawdopodobne jest równie , eby zmianie uległy czas wykonania lub przestrzeń wykorzystywana przez ich programy. I w jednym, i w drugim przypadku obiekt musi zawierać jedną kopię składnika odpowiadającego klasie .CPEWEJ. W większości przypadków klasa nieposiadająca klas bazowych będzie łatwiejsza do zro- zumienia i rozbudowy ni równowa na klasa wykorzystująca dziedziczenie prywatne. Zastosowanie zło enia oznacza równie , e późniejsze dodanie nowej klasy bazowej będzie wymagać dziedziczenia pojedynczego, a nie wielokrotnego. Na wielu platformach kod wykorzystujący dziedziczenie wielokrotne jest zauwa alnie wolniejszy i większy od kodu, którym zastosowano dziedziczenie pojedyncze, a ponadto jest zawsze trudniej- szy do zrozumienia. Wyjątek od tej reguły ma miejsce w przypadku, gdy w klasie pochodnej trzeba przesłonić funkcję wirtualną klasy bazowej, a nie chcemy tej klasy bazowej udostępniać w pu- blicznym interfejsie. Dziedziczenie prywatne stanowi w takiej sytuacji najprostsze, a nie- kiedy jedyne rozwiązanie (jeśli przesłaniana funkcja wirtualna to destruktor). Załó my, na przykład, e korzystamy ze środowiska języka C++, które obsługuje me- chanizm tzw. zbierania nieu ytków (ang. garbage collection) w przypadku obiektów wy- prowadzonych z klasy DKGTCNP[. Ka de wywołanie funkcji DKGTCLAPKGW[VMK będzie powodować usunięcie tych „zbieralnych” obiektów, do których nie mo na się odwołać za pomocą istniejących wskaźników: MNCUC DKGTCNP[ ] RWDNKE DKGTCNP[ XKTVWCN `DKGTCNP[ ]_ _
  • 26. 82 C++. Strategie i taktyki. Vademecum profesjonalisty XQKF DKGTCLAPKGW[VMK ] DKGTCNP[
  • 27. ER YJKNG ER PCLFAPKGQUKCICNP[AQDKGMV FGNGVG ER _ Załó my ponadto, e projektujemy klasę podlegającą procesowi zbieraniu nieu ytków, która reprezentuje węzły grafu. Chocia przed u ytkownikami nie będziemy mogli naj- prawdopodobniej ukryć faktu, e nasz węzeł podlega zbieraniu nieu ytków, to mo emy ukryć wybór procedury zbierania nieu ytków. Realizujemy to przez u ycie klasy DKG TCNP[ jako prywatnej klasy bazowej: ENCUU 9GGN RTKXCVG DKGTCNP[ ] RWDNKE XKTVWCN `9GGN UEGIÎ [ RQOKPKúVQ _ Przesłaniając destruktor wirtualny zapewniamy, e instrukcja FGNGVG ER występująca w treści funkcji DKGTCLAPKGW[VMK w przypadku, gdy będzie dotyczyć obiektu klasy 9GGN, spowoduje wywołanie destruktora klasy 9GGN. Dzięki zastosowaniu dziedzicze- nia prywatnego zachowujemy mo liwość zmiany implementacji klasy 9GGN polegającej na u yciu jakiegoś innego mechanizmu zbierania nieu ytków. KGFKEGPKG EJTQPKQPG Dziedziczenie chronione stosowane jest w przypadku, gdy dziedziczenie wchodzi w skład interfejsu dla klas pochodnych, lecz nie jest elementem interfejsu dla u ytkowników. Chroniona klasa bazowa jest jak prywatna klasa bazowa, która jest znana wszystkim klasom pochodnym: ENCUU .CPEWEJ ]
  • 28. _ ENCUU 0WOGTAVGNGHQPW RTQVGEVGF .CPEWEJ ]
  • 29. _ ENCUU 0WOGTAOKGLUEQY[ RWDNKE 0WOGTAVGNGHQPW ]
  • 30. _ Funkcje składowe klasy 0WOGTAOKGLUEQY[ mają dostęp do składowych publicznych i chro- nionych części podchodzącej od klasy .CPEWEJ. Autor osobiście nigdy nie wykorzystywał dziedziczenia chronionego i nigdy nie słyszał tak e o jego zastosowaniu w powa nym projekcie. Wszystkie powody do niestosowania dziedziczenia prywatnego dotyczą równie dziedziczenia chronionego — zamiast chro- nionej klasy bazowej prościej jest zazwyczaj posiadać chronioną składową: ENCUU .CPEWEJ ]
  • 31. _ ENCUU 0WOGTAVGNGHQPW] RTQVGEVGF .CPEWEJ U
  • 32. Rozdział 4. Dziedziczenie 83 UEGIÎ [ RQOKPKúVQ _ ENCUU 0WOGTAOKGLUEQY[ RWDNKE 0WOGTAVGNGHQPW ]
  • 33. _ Taka przeróbka znacznie upraszcza hierarchię dziedziczenia. Wydajność jest taka sama, a funkcje składowe klasy 0WOGTAOKGLUEQY[ mają wcią dostęp do części obiektu pocho- dzącej od klasy .CPEWEJ (chocia teraz muszą odwoływać się do składowej U). Nie oznacza to wcale, e dziedziczenie chronione nigdy się nie przydaje — jeśli skła- dowe klasy pochodnej muszą przesłonić funkcje wirtualne występujące w (chronionej) klasie bazowej, to dziedziczenie chronione mo e stanowić odpowiednie rozwiązanie. Jeśli jednak mo na zastosować zło enie, to tak nale y zrobić — korzystanie z mało znanych „zakamarków” języka (takich jak dziedziczenie chronione) sprawia, e programy są trudniejsze do zrozumienia. IQFPQ è CDUVTCMELCOK MNCU[ DCQYGL W klasie pochodnej mo na przesłonić wirtualną funkcję składową klasy bazowej, dekla- rując ją ponownie z tą samą nazwą i z taką samą listą argumentów: ENCUU 2QLCF ] RWDNKE XKTVWCN XQKF RT[URKGU FQWDNG FQWDNG RTGFMQUE _ ENCUU 5COQEJQF RWDNKE 2QLCF ] RWDNKE XKTVWCN XQKF RT[URKGU FQWDNG _ ENCUU 1MTGVARQFYQFP[ RWDNKE 2QLCF ] RWDNKE XKTVWCN XQKF RT[URKGU FQWDNG _ Przy dziedziczeniu istnieje jednak znacznie silniejsze ograniczenie dotyczące składowych RT[URKGU klas 5COQEJQF oraz 1MTGVARQFYQFP[ ni samo wymaganie poprawności typów. Funkcja składowa klasy pochodnej powinna być zgodna z modelem abstrakcyjnym klasy bazowej. Chocia poszczególne implementacje mogą być ro ne, to ka dy obiekt klasy wyprowadzonej z klasy 2QLCF powinien „przyspieszać tak, jak robi to 2QLCF” — co- kolwiek miałoby to znaczyć. Jest to ograniczenie semantyczne — nie mo na go wyrazić w języku C++, kompilator C++ nie mo e więc sprawdzić, czy zostało spełnione. W przypadku klasy 2QLCF, model abstrakcyjny funkcji RT[URKGU mógłby określać, e przyspieszenie pojazdu zmienia jego RTGFMQUE o określoną wartość, tj.: przyspiesz (x ) ⇒ ( predkoscnowa == predkoscstara + x ) Gdy tylko ta część abstrakcji zostanie opisana, wszystkie klasy pochodne powinny być z nią zgodne.
  • 34. 84 C++. Strategie i taktyki. Vademecum profesjonalisty Dlaczego jest to wa ne? Jeśli wszystkie klasy pochodne są zgodne z modelem abstrak- cyjnym, u ytkownicy mogą tworzyć kod oparty na tym modelu: XQKF CVT[OCL 2QLCF R ] RRT[URKGU RRTGFMQUE _ i kod ten będzie działać w przypadku wszystkich Pojazdów: 1MTGVARQFYQFP[ QTGN CVT[OCL QTGN 5COQEJQF XQNMUYCIGP CVT[OCL XQNMUYCIGP W przyszłości mogą zostać dodane nowe rodzaje obiektów typu 2QLCF i będą one po- prawnie działać z kodem, który został zaimplementowany w czasach, kiedy one jeszcze nie istniały! ENCUU 5COQNQV RWDNKE 2QLCF ] RWDNKE XKTVWCN XQKF RT[URKGU FQWDNG _ 5COQNQV DQGKPIA CVT[OCL DQGKPIA /KGLO[ PCFKGLú G LGUVG O[ PC KGOK Zaimplementowaliśmy funkcję, która, dzięki zastosowaniu wywołań kilku operacji abs- trakcyjnych (wirtualnych funkcji składowych), działa z ka dą klasą, która jest wyprowa- dzona z klasy 2QLCF i poprawnie realizuje te operacje abstrakcyjne, nie posiadając jedno- cześnie adnej innej wiedzy na temat tych obiektów. To jest właśnie jedna z głównych zalet projektowania obiektowego. Jeśli związek pomiędzy składowymi RTGFMQUE i RT[URKGU nie będzie wyraźnie udoku- mentowany i rozumiany przez projektantów, znajdzie się ktoś, kto zaimplementuje klasę pochodną, która nie będzie zgodna z modelem abstrakcyjnym, np.: ENCUU TCIUVGT RWDNKE 5COQEJQF ] RWDNKE XKTVWCN XQKF RT[URKGU FQWDNG _ XQKF TCIUVGTRT[URKGU FQWDNG FGNVC ] TCIUVGT[ RT[URKGUCLæ DCTFQ U[DMQ 5COQEJQFRT[URKGU
  • 35. FGNVC _ Autor klasy TCIUVGT źle zrozumiał, jak powinna działać funkcja składowa RT[URKGU. Dlatego klasa TCIUVGT nie jest zgodna z modelem abstrakcyjnym klasy 2QLCF. Rozwa my, co się stanie, jeśli dla obiektu typu TCIUVGT poruszającego się z prędkością 100 km/h wywołamy funkcję CVT[OCL. Funkcja CVT[OCL wykona następujące wywołanie RRT[URKGU RRTGFMQUE
  • 36. Rozdział 4. Dziedziczenie 85 które w tym przypadku spowoduje wywołanie funkcji TCIUVGTRT[URKGU co z kolei wywoła funkcję 5COQEJQFRT[URKGU Po wywołaniu funkcji CVT[OCL nasz TCIUVGT będzie jechał z prędkością 100 km/h w przeciwnym kierunku! Z pewnością programista nie to miał na myśli. Pomimo e kod spełnia ograniczenia dotyczące typów narzucane przez język — kompilacja przebiega bez problemów — to jego działanie nie jest prawidłowe, poniewa klasa TCIUVGT nie jest zgodna z modelem abstrakcyjnym klasy 2QLCF. (WPMELG E[UVQ YKTVWCNPG Nasza pierwotna klasa 2QLCF zawiera deklarację funkcji składowej RT[URKGU. Umie- ściliśmy ją w tej klasie, poniewa RT[URKGU jest operacją, która jest pojęciowo po- prawna dla wszystkich pojazdów. Oczekujemy, e wersja tej funkcji występująca w kla- sie bazowej zostanie przesłonięta w ka dej klasie pochodnej. W jaki sposób powinniśmy zaimplementować funkcję 2QLCFRT[URKGU? Nie prze- widujemy w ogóle tworzenia obiektów typu 2QLCF. Klasa 2QLCF jest za to klasą bazową, która opisuje pojęcia wspólne dla zbioru klas pochodnych. W zamierzeniu klasa 2QLCF ma być u ywana wyłącznie jako klasa bazowa, a funkcja RT[URKGU zostanie przesło- nięta w ka dej klasie pochodnej. Nie spodziewamy się więc, eby ktoś kiedykolwiek wywołał funkcję 2QLCFRT[URKGU. Jedno podejście mogłoby polegać na zdefinio- waniu wersji, która w przypadku wywołania wyświetli komunikat o błędzie: XQKF 2QLCFRT[URKGU FQWDNG ] EGTT 9[YQ CPC HWPMELC 2QLCFRT[URKGU!P CDQTV _ lecz takie podejście będzie wykrywać brak przesłonięcia funkcji RT[URKGU dopiero podczas wykonywania. Lepszym rozwiązaniem będzie wykorzystanie pewnego mecha- nizmu języka C++, który pozwoli wykryć to podczas kompilacji — przez deklarację funk- cji 2QLCFRT[URKGU jako tzw. funkcji czysto wirtualnej. Dzięki zadeklarowaniu klasy 2QLCF jako klasy abstrakcyjnej, kompilator będzie genero- wać błąd kompilacji przy ka dej próbie utworzenia obiektu typu 2QLCF. Nie musimy sobie zadawać trudu definiowania namiastek funkcji dla funkcji składowych klasy bazowej. Z tego powodu zastosowanie funkcji czysto wirtualnych i abstrakcyjnych klas bazowych zalecane jest w przypadku klas takich jak 2QLCF, które opisują zbiory klasy pochodnych. Destruktor nigdy nie powinien być funkcją czysto wirtualną: ENCUU 2QLCF ] RWDNKE XKTVWCN `2QLCF [ RQO[U UEGIÎ [ RQOKPKúVQ _
  • 37. 86 C++. Strategie i taktyki. Vademecum profesjonalisty Powtórka: Funkcje czysto wirtualne i abstrakcyjne klasy bazowe Wirtualna funkcja składowa, w której w deklaracji po liście argumentów występuje wyrażenie : ENCUU % ] XKTVWCN XQKF H _ jest tzw. funkcją czysto wirtualną. Nie trzeba podawać żadnej definicji funkcji czysto wirtualnej %H . Każda klasa, która deklaruje lub dziedziczy funkcję czysto wirtualną jest abstrakcyjną klasą bazową. Próba utworzenia obiektu abstrakcyjnej klasy bazowej spowoduje błąd podczas kompilacji. Jeśli w klasie wyprowadzonej z klasy % funkcja %H zostanie przesłonięta, to ta klasa będzie już klasą konkretną (nieabstrakcyjną): ENCUU RWDNKE % ] XQKF H _ Abstrakcyjna klasa bazowa służy do deklarowania interfejsu bez deklarowania pełnego zbioru implementacji dla tego interfejsu. Taki interfejs określa operacje abstrakcyjne realizowane przez wszystkie obiekty wyprowadzone z tej klasy — obowiązek zapewnienia implementacji dla tych operacji abstrakcyjnych spoczywa już na klasach pochodnych. Na przykład: ENCUU 2QLCF ] RWDNKE XKTVWCN FQWDNG RT[URKGU FQWDNG XKTVWCN FQWDNG RTGFMQUE _ Ponieważ klasa 2QLCF jest abstrakcyjna, próba utworzenia obiektu typu 2QLCF powoduje błąd kompilacji: 2QLCF R $ æF MQORKNCELK MNCUC 2QLCF LGUV CDUVTCME[LPC Aby móc użyć klasy 2QLCF OWUKO[ dla niej utworzyć klasy pochodne: ENCUU 5COQEJQF RWDNKE 2QLCF ] RWDNKE XKTVWCN FQWDNG RT[URKGU FQWDNG XKTVWCN FQWDNG RTGFMQUE _ ENCUU 4QYGT RWDNKE 2QLCF ] RWDNKE XKTVWCN FQWDNG RT[URKGU FQWDNG XKTVWCN FQWDNG RTGFMQUE _ Ponieważ w klasach 5COQEJQF oraz 4QYGT wszystkie funkcje czysto wirtualne klasy bazowej zostały przesłonięte, możemy tworzyć obiekty obydwu klas. Chociaż nie mogą istnieć żadne obiekty typu 2QLCF, to jednak możemy używać wskaźników i refe- rencji do tego typu: XQKF CVT[OCL 2QLCF R ] RRT[URKGU RRTGFMQUE _
  • 38. Rozdział 4. Dziedziczenie 87 Klasa pochodna, która dziedziczy (nie przesłania) funkcję czysto wirtualną jest także abstrakcyjna: ENCUU 2QLCFANCFQY[ RWDNKE 2QLCF ] _ 2QLCFANCFQY[ R $ æF MQORKNCELK MNCUC 2QLCFANCFQY[ LGUV CDUVTCME[LPC Destruktor 2QLCF`2QLCF będą wywoływać destruktory ka dej klasy wyprowadzonej z klasy 2QLCF. Poniewa definicja tego destruktora musi istnieć (w przeciwnym razie otrzy- mamy błędy modułu ładującego), deklarowanie go jako czysto wirtualnego nie ma sensu. 5EGIÎ [ K RW CRMK YKæCPG FKGFKEGPKGO Sposób obsługi dziedziczenia przez język C++ zawiera kilka sztuczek. Przyjrzyjmy się im: 'NGOGPV[ PKGRQFNGICLæEG FKGFKEGPKW Podczas korzystania z mechanizmu dziedziczenia nale y zawsze pamiętać o elementach, które nie są dziedziczone po klasie bazowej: Konstruktory (w tym konstruktor kopiujący). Jeśli nie zadeklarujemy konstruktora kopiującego, automatycznie zostanie utworzony konstruktor kopiujący, który będzie wywoływać konstruktory kopiujące niestatycznych danych składowych oraz klas bazowych. Destruktor. Jeśli nie zadeklarujemy destruktora, a dowolna z niestatycznych danych składowych lub klas bazowych posiada destruktor, to automatycznie zostanie utworzony destruktor, który będzie wywoływać destruktory niestatycznych danych składowych oraz klas bazowych. Destruktor ten będzie wirtualny, jeśli dowolna z klas bazowych posiada destruktor wirtualny. Operator przypisania. Jeśli nie zadeklarujemy operatora przypisania, automatycznie zostanie utworzony operator przypisania, który będzie wywoływać operatory przypisania niestatycznych danych składowych oraz klas bazowych. Ukryte funkcje składowe. Jeśli funkcja składowa klasy bazowej nie jest przesłonięta w klasie pochodnej, a w tej klasie pochodnej zadeklarowana jest funkcja o tej samej nazwie, lecz o ró nych argumentach, to funkcja występująca w klasie bazowej będzie ukryta. Na przykład: ENCUU 5COQEJQF ] RWDNKE 2QQUVC æ VTG è RQOKPKúVQ XQKF MKGTWL KPV UVQRPKG _ ENCUU #WVQRKNQV ] RWDNKE #WVQRKNQV _
  • 39. 88 C++. Strategie i taktyki. Vademecum profesjonalisty ENCUU +PVGNKIGPVP[AUCOQEJQF RWDNKE 5COQEJQF ] RWDNKE 2QQUVC æ VTG è RQOKPKúVQ XQKF MKGTWL #WVQRKNQV 7MT[YC HWPMELú 5COQEJQFMKGTWL KPV _ Nasz +PVGNKIGPVP[AUCOQEJQF mo e być kierowany za pomocą autopilota, lecz jednocześnie ukryliśmy wersję funkcji MKGTWL występującą w klasie bazowej: +PVGNKIGPVP[AUCOQEJQF U UMKGTWL $ æF MQORKNCELK PKG OQ PC WVYQT[è QDKGMVW V[RW #WVQRKNQV V[RW KPV Jeśli nie chcemy, aby funkcja klasy bazowej była ukryta, musimy ją ponownie zadeklarować w klasie pochodnej: ENCUU +PVGNKIGPVP[AUCOQEJQF RWDNKE 5COQEJQF ] RWDNKE 2QQUVC æ VTG è RQOKPKúVQ XQKF MKGTWL KPV K ] 5COQEJQFMKGTWL K _ XQKF MKGTWL #WVQRKNQV _ Niektóre kompilatory języka C++, w przypadku gdy funkcja zadeklarowana w klasie pochodnej powoduje ukrycie funkcji klasy bazowej, generują ostrze enie. 5VQUQYCPKG U QYC MNWEQYGIQ XKTVWCN Y MNCUKG RQEJQFPGL Przy przesłanianiu funkcji wirtualnej (lub czysto wirtualnej) nie trzeba jawnie określać słowa kluczowego XKTVWCN — kompilator „zauwa y”, e dana funkcja składowa posiada tę samą nazwę i te samy typy argumentów co funkcja wirtualna zadeklarowana w klasie bazowej: ENCUU $CQYC ] RWDNKE XKTVWCN XQKF H _ ENCUU 2QEJQFPC RWDNKE $CQYC ] RWDNKE XQKF H TÎYPQYC PG FGMNCTCELK XKTVWCN XQKF H _ Umieszczanie słowa kluczowego XKTVWCN jest jednak dobrym zwyczajem w takim przy- padku, poniewa dzięki niemu kod staje się bardziej oczywisty. Znaczenie programu jest w obydwu przypadkach takie samo. (WPMELG YKTVWCNPG Y[YQ [YCPG RQKQOW MQPUVTWMVQTÎY K FGUVTWMVQTÎY W przypadku gdy funkcje wirtualne wywoływane są z poziomu konstruktora lub de- struktora obiektu, ich działanie jest nieco inne. Gdy konstruktor tworzy część bazową klasy pochodnej, konstruowany obiekt traktowany jest tak, jakby był obiektem klasy bazowej, a nie klasy pochodnej. Oznacza to, e wywołanie funkcji wirtualnej spowoduje
  • 40. Rozdział 4. Dziedziczenie 89 wykonanie takiej wersji tej funkcji, która będzie odpowiednia dla klasy bazowej, której konstruktor będzie aktualnie wykonywany, a PKG dla klasy pochodnej. Na przykład: ENCUU $CQYC ] RWDNKE $CQYC XKTVWCN XQKF MQOWPKMCVAFKCIP ] EQWV $CQYC$CQYC P _ _ ENCUU 2QEJQFPC RWDNKE $CQYC ] RWDNKE 2QEJQFPC XKTVWCN XQKF MQOWPKMCVAFKCIP ] EQWV 2QEJQFPC2QEJQFPC P _ _ $CQYC$CQYC ] MQOWPKMCVAFKCIP _ OCKP ] $CQYC D 2QEJQFPC R _ Program ten wypisze na ekranie: $CQYC$CQYC $CQYC$CQYC Wywołanie funkcji MQOWPKMCVAFKCIP w treści konstruktora klasy $CQYC będzie zawsze powodować wywołanie składowej $CQYCMQOWPKMCVAFKCIP , nawet jeśli konstruktor ten tworzy część typu $CQYC obiektu typu 2QEJQFPC. To zagadkowe zachowanie spowodowane jest faktem, e części obiektu pochodzące od klasy bazowej konstruowane są przed jego danymi składowymi. W momencie tworzenia części $CQYC obiektu typu 2QEJQFPC, nie istnieje jeszcze adna z danych składowych klasy 2QEJQFPC. Wywołanie wersji funkcji wirtualnej z klasy 2QEJQFPC nie miałoby więc sensu, poniewa wersja ta próbowałby prawdopodobnie odwoływać się do niezainicjalizowanych danych składowych klasy 2QEJQFPC (patrząc na ten problem z innej strony, mo na powie- dzieć, e gdy wywoływany jest konstruktor klasy $CQYC, obiekt nie jest jeszcze właściwie obiektem typu 2QEJQFPC, więc składowe klasy 2QEJQFPC nie powinny być wywoływane). Ta sama logika ma zastosowanie wobec wywołań funkcji wirtualnych w treści destruktorów: $CQYC`$CQYC ] MQOWPKMCVAFKCIP _ Ten destruktor będzie zawsze wywoływał funkcję $CQYCMQOWPKMCVAFKCIP, nawet jeśli niszczymy część typu $CQYC obiektu typu 2QEJQFPC. W chwili wywołania destruktora klasy $CQYC dane składowe klasy 2QEJQFPC są ju zniszczone, więc wywołanie wersji funkcji MQOWPKMCVAFKCIP z klasy 2QEJQFPC nie miałoby sensu.
  • 41. 90 C++. Strategie i taktyki. Vademecum profesjonalisty Pamiętajmy, e takie szczególne zachowanie ma miejsce tylko w przypadku, gdy funkcja wirtualna wywoływana jest dla obiektu będącego w trakcie konstrukcji lub niszczenia. Wywołanie funkcji wirtualnej dla jakiegoś innego obiektu będzie działać normalnie, nawet jeśli ma miejsce w treści konstruktora czy destruktora: $CQYC$CQYC ] MQOWPKMCVAFKCIP 9[YQ WLG HWPMELú $CQYCMQOWPKMCVAFKCIP $CQYC
  • 42. DR PGY 2QEJQFPC DR MQOWPKMCVAFKCIP 9[YQ WLG HWPMELú 2QEJQFPCMQOWPKMCVAFKCIP _ 9 UMTÎEKG Dziedziczenie jest związkiem generalizacji (specjalizacji), czyli relacją typu jest — obiekty implementowane przez klasę pochodną powinny reprezentować podzbiór obiektów implementowanych przez klasę bazową. Dziedziczenie publiczne stosujemy w przypadku, gdy dziedziczenie jest elementem interfejsu. Dziedziczenie prywatne lub chronione stosujemy tylko wtedy, gdy dziedziczenie stanowi ukryty szczegół implementacyjny. W większości przypadków zamiast dziedziczenia prywatnego nale y zastosować zło enie — wyjątkiem jest sytuacja, gdy w klasie pochodnej trzeba przesłonić funkcję wirtualną zadeklarowaną w (prywatnej) klasie bazowej. Funkcja wirtualna przesłonięta w klasie pochodnej powinna być zgodna z modelem abstrakcyjnym klasy bazowej. Konstruktory, destruktory oraz operatory przypisania nie podlegają dziedziczeniu. 2[VCPKC Załó my, e w naszej hierarchii klas 2QLCF chcielibyśmy zdefiniować RTGFMQUEA NQVW pojazdu lądowego jako synonim jego składowej RTGFMQUE. W jaki sposób wpłynie to na hierarchię klas 2QLCF? Czy zmiana ta uprości, czy raczej utrudni korzystanie z tych klas? W jaki sposób zapewnisz, aby klasa 2QLCF potwierdzała, e ka da implementacja funkcji RT[URKGU w klasie pochodnej jest zgodna z modelem abstrakcyjnym? (Wskazówka: mo esz sprawić, aby klasy pochodne zamiast funkcji RT[URKGU przesłaniały jakieś inne funkcje.) Jaki to będzie miało wpływ na czas wykonania? Funkcję czysto wirtualną mo na (lecz nie trzeba) zdefiniować. Taką funkcję mo na później wywołać jedynie bezpośrednio przy u yciu specyfikatora : 5COQEJQF U U2QLCFRT[URKGU W jaki sposób mo na by wykorzystać tę właściwość? Czy istnieje jakieś lepsze rozwiązanie, które nie będzie wykorzystywać takiej niejasnej cechy języka?