SlideShare uma empresa Scribd logo
1 de 49
Baixar para ler offline
IDZ DO
         PRZYK£ADOWY ROZDZIA£

                           SPIS TRE CI   C++Builder 6.
                                         Æwiczenia
           KATALOG KSI¥¯EK
                                         Autor: Andrzej Daniluk
                      KATALOG ONLINE     ISBN: 83-7197-986-X
                                         Format: B5, stron: 128
       ZAMÓW DRUKOWANY KATALOG           Przyk³ady na ftp: 1391 kB


              TWÓJ KOSZYK
                    DODAJ DO KOSZYKA     Borland C++ Builder to jedno z najwygodniejszych rodowisk programistycznych dla
                                         programistów C++, platforma ciesz¹ca siê du¿¹ popularno ci¹ i maj¹ca za sob¹ d³ug¹
                                         historiê. W jêzyku C++ napisano wiele aplikacji dla Windows, z których znaczna czê æ
         CENNIK I INFORMACJE             powsta³a w³a nie w Builderze.
                                         „C++ Builder. Æwiczenia” to uzupe³nienie poprzedniej publikacji Wydawnictwa Helion,
                   ZAMÓW INFORMACJE      zatytu³owanej „C++ Builder 5. Æwiczenia praktyczne”. Ksi¹¿ka omawia zmiany, jakie
                     O NOWO CIACH        wprowadzono w nowej, szóstej ju¿ wersji C++ Buildera, a tak¿e porusza wiele
                                         zagadnieñ, które nie znalaz³y siê w ksi¹¿ce traktuj¹cej o poprzedniej edycji tego
                       ZAMÓW CENNIK      programu. Informacje zosta³y przekazane w formie æwiczeñ z dok³adnym omówieniem
                                         prezentowanego kodu ród³owego.
                                         Znajdziesz w niej miêdzy innymi:
                 CZYTELNIA                  • Zagadnienia zwi¹zane z kompatybilno ci¹ pomiêdzy wersjami pi¹t¹ i szóst¹
          FRAGMENTY KSI¥¯EK ONLINE            C++ Buildera
                                            • Seriê æwiczeñ przybli¿aj¹cych jêzyk C++
                                            • Omówienie rodowiska IDE C++ Builder
                                            • Æwiczenia z programowania w C++ z wykorzystaniem C++ Builder
                                            • Æwiczenia z pisania aplikacji wielow¹tkowych
                                            • Sposoby tworzenia w³asnych komponentów




Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Spis treści
                      Wstęp.............................................................................................................................................................. 5
Rozdział 1.           Konfiguracja projektu ............................................................................................................................ 7
                      Kompatybilność wersji Buildera ..................................................................................................8
                      Podsumowanie .............................................................................................................................9

Rozdział 2. C++ w pigułce............................................................................................................................................ 11
                      Pliki nagłówkowe.......................................................................................................................11
                      Przestrzenie nazw standardowych..............................................................................................14
                      Klasy wejścia-wyjścia języka C++ ............................................................................................14
                          Obsługa plików z wykorzystaniem klasy ios.......................................................................17
                      Struktury w C++.........................................................................................................................18
                          Samodzielne tworzenie plików nagłówkowych...................................................................21
                      Klasy w C++ ..............................................................................................................................22
                          Konstruktor i destruktor .......................................................................................................27
                          Inne spojrzenie na klasy. Własności ....................................................................................29
                      Funkcje przeładowywane ...........................................................................................................31
                          Niejednoznaczność ..............................................................................................................33
                      Funkcje ogólne ...........................................................................................................................34
                          Przeładowywanie funkcji ogólnych .....................................................................................36
                      Typ wyliczeniowy ......................................................................................................................37
                      Dziedziczenie .............................................................................................................................38
                      Funkcje wewnętrzne...................................................................................................................42
                      Realizacja przekazywania egzemplarzy klas funkcjom .............................................................43
                      Tablice dynamicznie alokowane w pamięci...............................................................................45
                      Tablice otwarte ...........................................................................................................................48
                      Wskaźniki do egzemplarzy klas.................................................................................................50
                      Wskaźnik this .............................................................................................................................51
                      Obsługa wyjątków......................................................................................................................52
                      Podsumowanie ...........................................................................................................................56

Rozdział 3. Środowisko programisty — IDE...................................................................................................... 57
                      Biblioteka VCL ..........................................................................................................................59
                         Karta Standard .....................................................................................................................59
                         Karta Additional...................................................................................................................61
                         Karta Win32.........................................................................................................................63
                         Karta System ........................................................................................................................65
                         Karta Dialogs .......................................................................................................................66
4                                                                                                                                C++Builder 6. Ćwiczenia


                      Biblioteka CLX ..........................................................................................................................67
                         Karta Additional...................................................................................................................67
                         Karta Dialogs .......................................................................................................................68
                      Podsumowanie ...........................................................................................................................68

Rozdział 4. C++ w wydaniu Buildera 6 ................................................................................................................ 69
                      Formularz ...................................................................................................................................69
                      Zdarzenia ....................................................................................................................................71
                      Rzutowanie typów danych .........................................................................................................78
                      Klasa TObject.............................................................................................................................78
                      Wykorzystujemy własne funkcje ...............................................................................................79
                      Wykorzystujemy własny, nowy typ danych ..............................................................................81
                      Widok drzewa obiektów — Object Tree View ..........................................................................84
                         Komponenty TActionManager i TActionMainMenuBar ....................................................84
                      Typy wariantowe........................................................................................................................89
                         Tablice wariantowe ..............................................................................................................91
                      Klasy wyjątków..........................................................................................................................93
                      Więcej o wskaźniku this.............................................................................................................96
                      Podsumowanie ...........................................................................................................................98

Rozdział 5. Biblioteka CLX ......................................................................................................................................... 99
                      Komponenty TTimer i TLCDNumber .......................................................................................99
                      Podsumowanie .........................................................................................................................103

Rozdział 6. Tworzymy własne komponenty ...................................................................................................... 105
                      Podsumowanie .........................................................................................................................110

Rozdział 7.           Aplikacje wielowątkowe ................................................................................................................... 111
                      Funkcja BeginThread() ............................................................................................................111
                      Komponent TChart...................................................................................................................114
                      Podsumowanie .........................................................................................................................116

Rozdział 8. C++Builder jako wydajne narzędzie obliczeniowe............................................................. 119
                      Obliczenia finansowe ...............................................................................................................119
                      Podsumowanie .........................................................................................................................126
2.               Rozdział

                                                 C++ w pigułce
            Ten rozdział poświęcony jest skrótowemu omówieniu podstawowych pojęć, którymi po-
            sługujemy się tworząc programy w C++. Zagadnienia tutaj poruszane posiadają kluczowe
            znaczenie dla zrozumienia idei programowania zorientowanego obiektowo w środowisku
            C++. U ywana terminologia oraz zamieszczone w dalszej części rozdziału przykłady (o ile
            nie zostały u yte elementy z biblioteki VCL) zgodne są ze standardem ANSI X3J16/ISO
            WG21 języka C++1.




Pliki nagłówkowe
            W odró nieniu od programów pisanych w standardowym języku C, gdzie nie musimy
            zbytnio przejmować się dołączaniem do kodu źródłowego wielu plików nagłówkowych,
            w programach C++ nie mo na ich pominąć. Wynika to z faktu, i bardzo wiele funkcji
            bibliotecznych korzysta z własnych struktur oraz typów danych. W C++ ich definicje
            znajdują się właśnie w plikach nagłówkowych (ang. header files), które posiadają stan-
            dardowe rozszerzenie .h. C++ jest językiem bazującym na funkcjach, dlatego do pliku
            źródłowego programu musimy włączyć przy pomocy dyrektywy KPENWFG odpowiednie
            pliki zawierające wywoływane funkcje wraz z ich prototypami. Większość standardowych
            plików nagłówkowych znajduje się w katalogu instalacyjnym INCLUDE. W dalszej części
            rozdziału wiadomości na temat praktycznego wykorzystania zarówno standardowych, jak
            i samodzielnie tworzonych plików nagłówkowych znacznie rozszerzymy.

            Prosty przykład wykorzystania standardowych plików nagłówkowych iostream.h (zawiera
            definicje klas umo liwiające wykonywanie ró norodnych operacji wejścia-wyjścia na
            strumieniach) oraz conio.h (zawiera funkcje obsługi ekranu) zawiera poni sze ćwiczenie.

1
    Musimy zauwa yć, i Borland C++Builder traktowany jako kompletne środowisko programistyczne
    z pewnych względów nie spełnia wymogów ISO.
12                                                                             C++Builder 6. Ćwiczenia



Ćwiczenie 2.1.
             1. Stwórzmy na dysku odrębny katalog (folder) nazywając go po prostu >. W katalogu
                 tym przechowywane będą wszystkie pliki wykorzystywane przez aktualnie pisany
                 program.
             2. Uruchamiamy C++Buildera 6. Poleceniem menu FileNewOtherConsole Wizard
                 otwórzmy nowy moduł. W okienku dialogowym Console Wizard w opcji Source Type
                 wybierzmy C++, zaś w drugim panelu odznaczmy Use VCL, Use CLX, Multi Thread
                 oraz wybierzmy Console Application, tak jak pokazuje to rysunek 2.1. Zaznaczenie
                 tej opcji powoduje, e program będzie traktował główny formularz tak, jakby był
                 normalnym okienkiem tekstowym. Pozostawienie aktywnej opcji Use CLX (CLX jest
                 skrótem od angielskiego terminu, określającego pewną klasę bibliotek wspomagających
                 proces projektowania aplikacji przenośnych pomiędzy Windows a Linux: Cluster
                 software runing under LinuX) spowoduje automatyczne dołączenie do programu pliku
                 nagłówkowego clx.h wspomagającego tworzenie aplikacji międzyplatformowych.

Rysunek 2.1.
Okno Console Wizard




             3. Potwierdzając przyciskiem OK przechodzimy do okna zawierającego szkielet kodu
                 przyszłego programu, tak jak pokazuje to rysunek 2.2.

Rysunek 2.2.
Kod modułu Unit1.cpp




             4. Programów naszych nie będziemy uruchamiać z linii poleceń, dlatego okno edycji
                 kodu wypełnimy tekstem pokazanym na wydruku 2.1. Następnie poleceniem
                 FileSave As… zapiszemy nasz moduł w katalogu 01 jako 7PKVERR. Projekt
                 modułu zapiszemy poleceniem FileSave Project As… w tym samym katalogu:
                 2TQLGMVADRT.
Rozdział 2.    C++ w pigułce                                                                           13


Wydruk 2.1. Kod modułu Unit01.cpp projektu Projekt_01.bpr
                KPENWFG KQUVTGCOJ
                KPENWFG EQPKQJ
                RTCIOC JFTUVQR
               KPV OCKP

               ]
                  ENTUET

                  EQWV  KG FQDT[        GPFN
                  IGVEJ

                  TGVWTP 
               _


               5. Po uruchomieniu programu poleceniem RunRun (F9), na ekranie w okienku
                 udającym tryb tekstowy Windows pojawi się napis powitania. Program opuszczamy
                 naciskając klawisz Enter.

              Jak widać, w skład tego programu wchodzą dwa pliki nagłówkowe: iostream.h oraz conio.h.
              Pierwszy z nich zdefiniowany jest w C++ i umo liwia wykonywanie szeregu operacji
              wejścia-wyjścia. Powodem włączenia pliku conio.h jest zastosowanie funkcji ENTUET

              (ang. clear screen) czyszczącej ekran tekstowy oraz funkcji IGVEJ
 (ang. get character)
              oczekującej na naciśnięcie dowolnego klawisza (wprowadzenie dowolnego znaku). U ycie
              dyrektywy RTCIOC JFTUVQR (ang. header stop) informuje kompilator o końcu listy plików
              nagłówkowych.

              Ka dy program pisany w C++ musi zawierać przynajmniej jedną funkcję. Główna funkcja
              OCKP
 jest tą, która zawsze musi istnieć w programie i zawsze wywoływana jest jako pierw-
              sza. Zestaw instrukcji właściwych danej funkcji musi być zawarty w nawiasach klamro-
              wych ]_, będących swojego rodzaju odpowiednikiem DGIKPGPF w Pascalu.
                 Instrukcje zawarte w nawiasach klamrowych nazywamy blokiem instrukcji (ang. code block);
                 jest on grupą logicznie powiązanych ze sobą elementów traktowanych jako niepodzielny
                 fragment programu.

              Ka da funkcja określonego typu powinna zwracać wartość tego samego typu. W powy szym
              przykładzie funkcja OCKP
 jest typu całkowitego KPV, zatem musi zwrócić do systemu
              taką samą wartość. Tutaj wykonaliśmy tę operację u ywając instrukcji TGVWTP , która
              jest niczym innym, jak jedną z mo liwych wartości powrotnych udostępnianych w następ-
              stwie wywołania funkcji KPV OCKP
. Je eli funkcja byłaby typu nieokreślonego, czyli
              XQKF (tzw. typ pusty, pusta lista parametrów), wówczas nie musielibyśmy zwracać do sys-
              temu adnej wartości, tak jak ilustruje to poni szy przykład:
               XQKF OCKP

               ]
                  ENTUET

                  EQWV  KG FQDT[        GPFN
                  IGVEJ

                  TGVWTP
               _

              Brak wartości zwracanej przez funkcję XQKF OCKP
 w powy szym przykładzie wynika
              z faktu, e w programach C++ nieokreślona wartość funkcji (lub pusta lista parametrów)
              równoznaczna jest ze słowem XQKF.
14                                                                    C++Builder 6. Ćwiczenia


     W języku C++ słowo EQWV identyfikuje ekran (ale nie formularz !), zaś wraz z operatorem
      pozwala wyprowadzić zarówno łańcuchy znaków, jak i zmienne wszystkich typów.
     Słowo GPFN (ang. end of line) odpowiada wysłaniu kombinacji znaków %4.( ustawiających
     kursor na początku następnego wiersza.




Przestrzenie nazw standardowych
     Studiując niektóre programy C++ mo emy zauwa yć, i przed słowami EQWV i GPFN mo e
     występować słowo UVF. Informuje ono kompilator o potrzebie korzystania z tzw. wy-
     znacznika przestrzeni nazw. Chodzi o to, aby kompilator wiedział, e u ywamy strumieni
     EQWV i GPFN z biblioteki standardowej:
       KPENWFG KQUVTGCOJ
      KPV OCKP

      ]
        WUKPI UVFEQWV
        WUKPI UVFGPFN
        EQWV  VGMUV  GPFN
        
      _

     Często te programiści, w celu uniknięcia niedogodności pisania UVF przed ka dym
     EQWV i GPFN, po prostu informują kompilator o potrzebie u ywania całej przestrzeni nazw
     standardowych, tj. e ka dy obiekt, który nie zostanie oznaczony, z zało enia będzie po-
     chodził z przestrzeni nazw standardowych. W tym przypadku, zamiast konstrukcji WUKPI
     UVFEQWV piszemy po prostu WUKPI PCOGURCEG UVF.
       KPENWFG KQUVTGCOJ
      KPV OCKP

      ]
         WUKPI PCOGURCEG UVF
         EQWV  VGMUV  GPFN
         
      _

     W ksią ce tej nie będziemy jawnie rozró niać przestrzeni nazw standardowych.




Klasy wejścia-wyjścia języka C++
     Język C++ posługuje się kilkoma predefiniowanymi łańcuchami wejścia-wyjścia. Dwa
     najbardziej podstawowe z nich, związane ze standardowym wejściem-wyjściem, to EQWV
     oraz EKP. Z pierwszym z nich zapoznaliśmy się ju wcześniej. Słowo EKP wraz z operato-
     rem pozwala wprowadzać zarówno łańcuchy znaków, jak i ró nego rodzaju zmienne.

     Oprócz opisanych predefiniowanych łańcuchów, w C++ zdefiniowany jest jeszcze szereg
     tzw. klas strumieni wejścia-wyjścia. Trzy podstawowe klasy wejścia-wyjścia to:
Rozdział 2.    C++ w pigułce                                                                     15


                 QHUVTGCO (ang. output file stream) — wyprowadzanie danych,
                 KHUVTGCO (ang. input file stream) — wprowadzanie danych,
                 HUVTGCO (ang. file stream) — wprowadzanie i wyprowadzanie danych.

              Dwa proste ćwiczenia pozwolą nam zapoznać się z właściwościami wymienionych klas.

Ćwiczenie 2.2.

              Zaprojektujemy program, którego jedynym zadaniem będzie odczytanie swojego własnego
              tekstu źródłowego zawartego w pliku .cpp i wyświetlenie go na ekranie. Kod tego pro-
              gramu, korzystającego z uniwersalnej klasy HUVTGCO, pokazany jest na wydruku 2.2.

Wydruk 2.2. Moduł Unit02.cpp projektu Projekt_02.bpr
                   KPENWFG KQUVTGCOJ
                   KPENWFG HUVTGCOJ
                   KPENWFG EQPKQJ
                   RTCIOC JFTUVQR

                KPV OCKP

                ]
                EJCT DWHQT=?
                HUVTGCO +P(KNG

                    ENTUET

                   +P(KNGQRGP
 7PKVERR 
                   YJKNG 
 +P(KNGGQH
 ]
                      +P(KNGIGVNKPG
DWHQT UKGQH
DWHQT
                      EQWV  DWHQT  GPFN
                   _
                    +P(KNGENQUG

                    IGVEJ

                    TGVWTP 
                  _


              Wykorzystanie omawianych na początku niniejszego podrozdziału klas wejścia-wyjścia
              wymaga włączenia do programu pliku nagłówkowego fstream.h, tak jak wykonaliśmy to
              w linii 2. programu.

              Dane z pliku będziemy wczytywać znak po znaku, zatem wymagane jest zadeklarowa-
              nie w linii 7. programu bufora danych typu znakowego EJCT o odpowiednim rozmiarze.

              Chocia budowę klas i ró ne aspekty ich wykorzystywania omówimy dokładniej
              w dalszej części rozdziału, jednak ju w tym miejscu zaczniemy posługiwać się odpo-
              wiednią terminologią. Omawiając deklarację z linii 8. w sposób tradycyjny, powiedzie-
              libyśmy, i została tam zadeklarowana zmienna +P(KNG typu HUVTGCO. Jednak w odnie-
              sieniu do klas wygodniej jest posługiwać się innym sformułowaniem — powiemy, e
              w linii 8. programu zadeklarowaliśmy egzemplarz +P(KNG klasy HUVTGCO (bardzo często
              u ywa się te sformułowania, e został utworzony strumień wejściowy +P(KNG).

              Jak zapewne wiesz, ka dy plik, którego zawartość chcemy w odpowiedni sposób wy-
              świetlić, musi być najpierw otwarty do czytania. Czynność tę wykonujemy w linii 9.
              poprzez odwołanie się do egzemplarza (obiektu) klasy HUVTGCO z jawnym wskazaniem
16                                                                           C++Builder 6. Ćwiczenia


           funkcji, jakiej ma u ywać do otwarcia pliku. W terminologii stosowanej w programowaniu
           zorientowanym obiektowo powiemy, i strumień wejściowy +P(KNG połączyliśmy z pli-
           kiem dzięki wywołaniu funkcji składowej klasy (metody) QRGP
, której argumentem jest
           nazwa pliku umieszczona w podwójnych apostrofach.

           W przypadku, gdy czytany plik nie znajduje się w aktualnym katalogu, nale y podać
           pełną ście kę dostępu według następującego przepisu:
             +P(KNGQRGP
 EEYDKNFAMQF[7PKVERR 

           Proces czytania i wyświetlania na ekranie zawartości pliku wykonywany jest w liniach
           11. – 14. przy pomocy instrukcji iteracyjnej YJKNG, która będzie wykonywana do czasu
           napotkania znacznika końca pliku. Osiągnięcie końca pliku wykrywamy za pomocą
           funkcji składowej GQH
 (ang. end of file).

           W linii 12. przy pomocy dwuparametrowej funkcji składowej IGVNKPG
 wczytujemy za-
           wartość pliku do bufora. Pierwszym parametrem tej funkcji jest zmienna DWHQT identyfi-
           kująca bufor danych wejściowych. Drugim parametrem jest jednoargumentowy operator
           czasu kompilacji UKGQH
 udostępniający długość zmiennej DWHQT. Operator ten wykorzy-
           stujemy w przypadku, gdy wymagamy, aby kod źródłowy programu był w du ej mierze
           przenośny, tzn. by mo na było wykorzystywać go na ró nego rodzaju komputerach. Bar-
           dzo często warunek przenośności kodu wymaga, aby ustalić rzeczywistą długość da-
           nych, np. typu EJCT.

           W linii 15. wywołujemy funkcję składową ENQUG
 zamykającą otwarty uprzednio plik.

Ćwiczenie 2.3.

           Obecne ćwiczenie ilustruje sposób posługiwania się klasami QHUVTGCO oraz KHUVTGCO.
           Poprzedni program został zmodyfikowany w taki sposób, aby po utworzeniu w aktual-
           nym katalogu nowego pliku mo na było zapisać w nim odpowiednie dane, którymi w tym
           przypadku są wartości funkcji UKP
 (sinus), której prototyp znajduje się w pliku nagłów-
           kowym math.h.

Wydruk 2.3. Moduł Unit03.cpp projektu Projekt_03.bpr
                 KPENWFG KQUVTGCOJ
                 KPENWFG HUVTGCOJ
                 KPENWFG OCVJJ
                 KPENWFG EQPKQJ
                 RTCIOC JFTUVQR

             KPV OCKP

             ]
                EJCT DWHQT=?
                ENTUET

              VYQTGPKG PQYGIQ RNKMW K CRKU FCP[EJ PC F[UM
                QHUVTGCO 1WV(KNG
 PQY[FCV 
                KH 
 1WV(KNG
                  TGVWTP 
                HQT 
KPV K K K


                  1WV(KNG  UKP
K  GPFN
                1WV(KNGENQUG
Rozdział 2.    C++ w pigułce                                                                           17


                QFE[V FCP[EJ 
                  KHUVTGCO +P(KNG
 PQY[FCV 
                  YJKNG 
 +P(KNGGQH
 ]
                    +P(KNGIGVNKPG
DWHQT UKGQH
DWHQT
                    EQWV  DWHQT  GPFN
                  _
                  +P(KNGENQUG


                   IGVEJ

                   TGVWTP 
               _


              Analizując powy sze zapisy łatwo zauwa ymy, i zaraz po utworzeniu nowego pliku,
              przy pomocy instrukcji warunkowej KH sprawdzamy, czy czynność ta została wykonana
              pomyślnie. W przypadku niemo ności stworzenia na dysku pliku o podanej nazwie,
              przy pomocy instrukcji TGVWTP  wywołujemy wartość powrotną funkcji OCKP
, co jest
              równoznaczne z opuszczeniem programu.

              W omawianym programie nie została u yta funkcja QRGP
. Funkcji tej nie u ywa się
              zbyt często korzystając z klas strumieni, z tego względu, i klasy HUVTGO, KHUVTGO oraz
              QHUVTGO posiadają odpowiednie konstruktory (inne funkcje składowe), które otwierają
              pliki automatycznie.



Obsługa plików z wykorzystaniem klasy ios
              Jak zapewne pamiętasz, istnieją dwa podstawowe rodzaje plików, którymi w praktyce po-
              sługujemy się najczęściej. Są to pliki tekstowe oraz binarne. Pliki tekstowe, stanowiące
              zbiór znaków ASCII (lub Unicode), przechowują zawarte w nich informacje w kolejnych
              wierszach, z których ka dy zakończony jest parą znaków %4 .(. Pliki binarne zawierające
              kodowane dane ró nią się od tekstowych tym, i informacje w nich zawarte nie są prze-
              znaczone do bezpośredniego oglądania — są zrozumiałe jedynie dla określonych progra-
              mów. Bardzo wygodny dostęp do ró nego rodzaju plików dają nam elementy klasy KQU.
              Wspomniano wcześniej, e jednym ze sposobów połączenia uprzednio utworzonego stru-
              mienia z plikiem jest wywołanie funkcji:
               XQKF QRGP
EQPUV EJCT
U KQUADCUGQRGPOQFG  KQUADCUGQWV ^
                         KQUADCUGKP NQPI RTQVGEVKQP  

              gdzie U oznacza nazwę pliku, która mo e zawierać pełną ście kę dostępu. Tryb otwarcia pliku
              określa parametr QRGPOQFG, który musi być przedstawiony w postaci jednej lub większej
              liczby określonych wartości, połączonych przy pomocy operatora binarnej sumy logicznej ^.
              W tabeli 2.1 zebrano dostępne wartości, jakie mo e przyjmować parametr QRGPOQFG.

              Natomiast parametr RTQVGEVKQP opcjonalnie określa otwarcie zwykłego pliku.

              Je eli zechcemy, aby plik został otworzony np. w trybie do dopisywania, wystarczy po-
              słu yć się bardzo prostą konstrukcją:
               QHUVTGCO 1WV(KNG
 PQY[FCV  KQUCRR

              A dopisywania w trybie binarnym:
               QHUVTGCO 1WV(KNG
 PQY[FCV  KQUCRR ^ KQUDKPCT[
18                                                                                     C++Builder 6. Ćwiczenia


Tabela 2.1. Dopuszczalne tryby otwarcia pliku
 Wartości openmode             Opis
     KQUCRR                  Otwarcie pliku w trybie do dopisywania
                               (dołączenie wprowadzanych danych na końcu pliku).
     KQUCVG                  Ustawienie wskaźnika pliku na jego końcu.
     KQUKP                   Otwarcie pliku w tzw. trybie wejściowym (w trybie do czytania).
                               Wartość domyślna dla strumienia KHUVTGCO.
     KQUQWV                  Otwarcie pliku w tzw. trybie wyjściowym (w trybie do zapisywania).
                               Wartość domyślna dla strumienia QHUVTGCO.
     KQUDKPCT[               Otwarcie pliku binarnego.
     KQUVTWPE                Po otwarciu zawartość pliku zostanie usunięta.

Ćwiczenie 2.4.

                Korzystając z tabeli 2.1 zmodyfikuj projekt Projekt_03.bpr (wydruk 2.3) w ten sposób,
                aby sprawdzić działanie pozostałych metod otwarcia pliku.




Struktury w C++
                Struktury, tworzące zbiór zmiennych zło onych z jednej lub z logicznie powiązanych kilku
                danych ró nych typów, zgrupowanych pod jedną nazwą, są bardzo wygodnym typem
                danych, często definiowanym przez programistów C++. Na potrzeby obecnych ćwiczeń
                przedstawimy dwa bardzo często stosowane sposoby deklaracji oraz u ywania struktur.
                Słowo kluczowe UVTWEV (struktura) ułatwia logiczne pogrupowanie danych ró nych typów.
                Po słowie UVTWEV w nawiasach klamrowych deklarujemy elementy składowe struktury
                wraz z ich typami bazowymi.

Ćwiczenie 2.5.

                Zbudujemy naprawdę prostą bazę danych, w której przechowywać będziemy pewne in-
                formacje o wybranych studentach, tak jak pokazano to na wydruku 2.4.

Wydruk 2.4. Moduł Unit04.cpp projektu Projekt_04.bpr ilustrującego prosty przykład wykorzystania
informacji zawartej w pewnej strukturze
                     KPENWFG KQUVTGCOJ
                     KPENWFG EQPKQJ
                     KPENWFG UVFNKDJ
                     RTCIOC JFTUVQR
                   UVTWEV   5VWFGPV]
                   EJCT     +OKG=?
                   EJCT     0CYKUMQ=?
                   HNQCV    'ICOKP/CVGOCV[MC
                   HNQCV    'ICOKP(K[MC
                   HNQCV   'ICOKP+PHQTOCV[MC
Rozdział 2.   C++ w pigułce                                                        19


               EJCT ,CMK5VWFGPV=?
              _

               XQKF 5VWFGPV+PHQ
KPV 5VWFGPV +PHQ
              
               KPV OCKP

               ]
               5VWFGPV CPG=?
               KPV KPFGZ
               EJCT DWHQT/=?DWHQT(=?DWHQT+=?
               ENTUET

               FQ ]
                   EQWV  +OKG 
                   EKPIGVNKPG
CPG=KPFGZ?+OKG UKGQH
CPG=KPFGZ?+OKG

                   EQWV  0CYKUMQ 
                   EKPIGVNKPG
CPG=KPFGZ?0CYKUMQ
                               UKGQH
CPG=KPFGZ?0CYKUMQ

                   EQWV  'ICOKP /CVGOCV[MC 
                   EKPIGVNKPG
DWHQT/ UKGQH
DWHQT/
                   CPG=KPFGZ?'ICOKP/CVGOCV[MC  CVQH
DWHQT/ CVQH


                   EQWV  'ICOKP (K[MC 
                   EKPIGVNKPG
DWHQT( UKGQH
DWHQT(
                   CPG=KPFGZ?'ICOKP(K[MC  CVQH
DWHQT(

                   EQWV  'ICOKP +PHQTOCV[MC 
                   EKPIGVNKPG
DWHQT+ UKGQH
DWHQT+
                   CPG=KPFGZ?'ICOKP+PHQTOCV[MC  CVQH
DWHQT+

                   EQWV  1RKPKC 
                   EKPIGVNKPG
CPG=KPFGZ?,CMK5VWFGPV
                               UKGQH
CPG=KPFGZ?,CMK5VWFGPV

                   EQWV  GPFN
                   KPFGZ


                 _ YJKNG 
KPFGZ

               HQT 
KPV K K K


                    5VWFGPV+PHQ
K CPG=K?
               IGVEJ

               TGVWTP 
               _
              
               XQKF 5VWFGPV+PHQ
KPV PWOGT 5VWFGPV +PHQ
               ]
               EQWV  1UQDC 
TGMQTF PT  
PWOGT
    GPFN
               EQWV  +OKú K 0CYKUMQ  +PHQ+OKG  
               EQWV  +PHQ0CYKUMQ  GPFN
               EQWV  'ICOKP /CVGOCV[MC
                      +PHQ'ICOKP/CVGOCV[MC  GPFN
               EQWV  'ICOKP (K[MC  +PHQ'ICOKP(K[MC  GPFN
               EQWV  'ICOKP +PHQTOCV[MC
                      +PHQ'ICOKP+PHQTOCV[MC  GPFN
               EQWV  1RKPKC  +PHQ,CMK5VWFGPV  GPFN
               _
20                                                                       C++Builder 6. Ćwiczenia


     W programie głównym w liniach 5. – 12. definiujemy strukturę 5VWFGPV, w której polach
     zapisywać będziemy interesujące nas informacje, czyli imię i nazwisko danej osoby,
     oceny z egzaminów z wybranych przedmiotów i na koniec naszą opinię o studencie.

     Poniewa chcemy mieć mo liwość przechowywania w polach struktury informacji o więk-
     szej liczbie osób, dlatego w linii 16. deklarujemy tablicę CPG typu strukturalnego 5VWFGPV.
     Informacje przechowywane w polach struktury będą indeksowane, musimy zatem za-
     deklarować w linii 17. zmienną KPFGZ typu całkowitego.

     Oceny z poszczególnych egzaminów deklarowane są w strukturze 5VWFGPV jako prosty
     typ zmiennopozycyjny HNQCV. W trakcie działania programu oceny te wpisywać bę-
     dziemy z klawiatury w postaci ciągu znaków, które w dalszym etapie powinny zostać
     przekonwertowane na konkretne liczby. Z tego powodu łańcuchy znaków reprezentują-
     cych poszczególne oceny będą przechowywane w odpowiednich buforach deklarowa-
     nych w linii 18. programu.

     Proces wypełniania poszczególnych pól tablicy struktur CPG odbywa się w liniach 20. –
     38. programu w pętli FQYJKNG. I tak, w pierwszej kolejności za pomocą funkcji składo-
     wej IGVNKPG
 strumienia wejściowego EKP wypełniamy pola +OKG oraz 0CYKUMQ tablicy
     struktur CPG (linie 22. – 24.). Elementy tablicy struktur (osoby) są indeksowane po-
     cząwszy od wartości .

     W linii 26. wczytujemy do bufora DWHQT/ ciąg znaków reprezentujących ocenę z wybra-
     nego przedmiotu. W linii 27. ciąg znaków znajdujący się w buforze zostanie zamienio-
     ny na liczbę typu zmiennopozycyjnego za pomocą zdefiniowanej w pliku nagłówko-
     wym stdlib.h funkcji CVQH
. W tej samej linii programu liczba ta zostanie wpisana do
     pola 'ICOKP/CVGOCV[MC tablicy struktur CPG z odpowiednim indeksem określającym
     konkretną osobę. W podobny sposób wypełniamy pozostałe pola tablicy struktur CPG do
     momentu, kiedy zmienna KPFGZ nie przekroczy wartości określającej liczbę „zapamięta-
     nych” osób.

     W dalszym etapie rozwoju naszego programu zajdzie prawdopodobnie potrzeba po-
     nownego wyświetlenia (lub wyszukania i wyświetlenia) informacji o wybranych oso-
     bach (lub konkretnej osobie). Musimy zatem zaprojektować prostą funkcję rozwiązują-
     cą ten problem. W C++ istnieje konieczność deklarowania prototypów samodzielnie
     definiowanych funkcji. Prototyp naszej funkcji 5VWFGPV+PHQ
 typu XQKF (funkcja nie
     zwraca adnej wartości) umieszczony jest w linii 13. programu. Funkcja posiada dwa
     parametry: pierwszy typu całkowitego KPV, określający numer osoby, drugi +PHQ typu
     strukturalnego 5VWFGPV, umo liwiający odwoływanie się do konkretnych pól struktury
     (informacji zawartych w strukturze).

     Zapis funkcji 5VWFGPV+PHQ
 znajduje się w liniach 44. – 53. naszego programu. Łatwo
     zauwa ymy, i odpowiednie dane pobierane są z określonych pól struktury poprzez
     strumień wyjściowy EQWV.

     Proces wyświetlania danych na ekranie odbywa się w liniach 39. – 40., gdzie zmienna ste-
     rująca K w pętli HQT
 przebiega ju tylko indeksy tablicy struktur CPG.

     Na rysunku 2.3 pokazano omawiany program w trakcie działania.
Rozdział 2.    C++ w pigułce                                                                        21


Rysunek 2.3.
Projekt Projekt_04.bpr
po uruchomieniu




Samodzielne tworzenie plików nagłówkowych
              Wspominaliśmy wcześniej, i w C++ bardzo wiele funkcji bibliotecznych korzysta z wła-
              snych struktur oraz typów danych, których definicje znajdują się w plikach nagłówkowych.
              Korzystając z faktu, i stworzyliśmy przed chwilą własny strukturalny typ danych, zmo-
              dyfikujemy Projekt_04.bpr w ten sposób, aby posługiwał się plikiem nagłówkowym zawie-
              rającym definicję struktury 5VWFGPV.

Ćwiczenie 2.6.
               1. Poleceniem menu FileNewOtherHeader File uaktywniamy okno edycji ułatwiające
                 tworzenie i zapisywanie na dysku własnych, nowo tworzonych plików nagłówkowych.
               2. Kod pliku zaczyna się od dyrektywy kompilacji warunkowej KHPFGH (ang. if not
                 defined — jeśli nie zdefiniowano). Za dyrektywą następuje pisana du ymi literami
                 nazwa makra z reguły rozpoczynająca się od znaku podkreślenia.
               3. Następnie, przy pomocy dyrektywy FGHKPG definiujemy nazwę makra w ten sposób,
                 aby zaczynała się od znaku podkreślenia. Nazwa makra powinna odpowiadać nazwie,
                 którą później nadamy plikowi nagłówkowemu.
               4. Po zdefiniowaniu makra, nale y zdefiniować własny typ strukturalny.
               5. Definicja makra kończy się dyrektywą kompilacji warunkowej GPFKH.
                    KHPFGH A567'06A* CNG PKG KHFGH
                    FGHKPG A567'06*
                   UVTWEV 5VWFGPV]
                     EJCT +OKG=?
                     EJCT 0CYKUMQ=?
                     HNQCV 'ICOKP/CVGOCV[MC
                     HNQCV 'ICOKP(K[MC
                     HNQCV 'ICOKP+PHQTOCV[MC
                     EJCT ,CMK5VWFGPV=?
                   _
                    GPFKH
22                                                                       C++Builder 6. Ćwiczenia


      6. Tak określony plik nagłówkowy zapiszemy w aktualnym katalogu pod nazwą
         UVWFGPVJ.

        Bardzo często (nawet przez nieuwagę) osoby rozpoczynające naukę C++ popełniają pewien
        błąd. Mianowicie zamiast dyrektywy KHPFGH u ywają bardzo podobnej w zapisie KHFGH
        (ang. if defined — jeśli zdefiniowano). Ró nica pomiędzy tymi dyrektywami jest dosyć
        wyraźna.
        Je eli za pomocą dyrektywy FGHKPG została wcześniej zdefiniowana pewna makrodefinicja,
        wówczas sekwencja instrukcji występująca pomiędzy dyrektywami KHFGH oraz GPFKH będzie
        zawsze kompilowana.
        Sekwencja instrukcji występująca pomiędzy dyrektywami KHPFGH oraz GPFKH będzie
        kompilowana jedynie wówczas, gdy dana makrodefinicja nie została wcześniej zdefiniowana.

      7. Tak przygotowany plik nagłówkowy zawierający definicję struktury 5VWFGPV bez
        problemu wykorzystamy w naszym programie. W tym celu wystarczy dołączyć
        go do kodu zaraz po dyrektywie RTCIOC JFTUVQR:
          
           RTCIOC JFTUVQR
           KPENWFG UVWFGPVJ
          XQKF 5VWFGPV+PHQ
KPV 5VWFGPV +PHQ
          

     Zmodyfikowany Projekt_04.bpr mo emy ju samodzielnie przetestować.




Klasy w C++
     Klasa jest jednym z podstawowych pojęć obiektowego języka C++. Przy pomocy słowa
     kluczowego ENCUU definiujemy nowy typ danych, będący w istocie połączeniem danych
     i instrukcji, które wykonują na nich działania. Umo liwia on tworzenie nowych (lub wyko-
     rzystanie istniejących) obiektów będących reprezentantami klasy. Konstrukcja klasy umo li-
     wia deklarowanie elementów prywatnych (ang. private), publicznych (ang. public) oraz
     chronionych (ang. protected). Domyślnie, w standardowym języku C++ wszystkie ele-
     menty klasy traktowane są jako prywatne, co oznacza, e dostęp do nich jest ściśle kontro-
     lowany i adna funkcja nie nale ąca do klasy nie mo e z nich korzystać. Je eli w definicji
     klasy pojawią się elementy publiczne, oznacza to, e mogą one uzyskiwać dostęp do innych
     części programu. Chronione elementy klasy dostępne są jedynie w danej klasie lub w kla-
     sach potomnych. Ogólną postać definicji klasy mo na przedstawić w sposób następujący:
      ENCUU 0CYC-NCU[
      ]
        RTKXCVG
          RT[YCVPG FCPG K HWPMELG
        RWDNKE
          RWDNKEPG FCPG K HWPMELG
        RTQVGEVGF
          EJTQPKQPG FCPG K HWPMELG

      _ 'IGORNCTG-NCU[  NKUVC GIGORNCT[ MNCU[
Rozdział 2.    C++ w pigułce                                                                           23


              Definicja klasy jest zawsze źródłem definicji jej obiektów. Jeszcze kilkanaście lat temu
              przed pojawieniem się wizualnych środowisk programistycznych słowo obiekt (ang.
              object) było jednoznacznie uto samiane z klasą2. Obecnie sytuacja nieco się skompliko-
              wała, gdy słowo obiekt otrzymało o wiele szersze znaczenie. Z tego względu wygodniej
              jest posługiwać się szeroko stosowanym w anglojęzycznej literaturze sformułowaniem
              egzemplarz klasy (ang. class instance). Otó , po zdefiniowaniu klasy tworzymy obiekt
              jej typu o nazwie takiej samej, jak nazwa klasy występująca po słowie ENCUU. Jednak klasy
              tworzymy po to, by stały się specyfikatorami typów danych. Je eli w instrukcji definicji
              klasy po zamykającym nawiasie klamrowym podamy pewną nazwę, utworzymy tym samym
              określony egzemplarz klasy, który od tej chwili traktowany jest jako nowy, pełnoprawny typ
              danych. Oczywiście jedna klasa mo e być źródłem definicji wielu jej egzemplarzy. Innym
              sposobem utworzenia egzemplarza danej klasy będzie następująca konstrukcja:
               
               ENCUU 0CYC-NCU[
               ]
                 RTKXCVG
                   RT[YCVPG FCPG K HWPMELG
                 RWDNKE
                   RWDNKEPG FCPG K HWPMELG
                 RTQVGEVGF
                   EJTQPKQPG FCPG K HWPMELG
               _
               
               KPV OCKP

               
               'IGORNCT-NCU[ 0CYC-NCU[
               


Ćwiczenie 2.7.

              Jako przykład stworzymy bardzo prostą w swojej budowie klasę 5VWFGPV, przy pomocy
              której będziemy mogli odczytać wybrane informacje o pewnej osobie.
               1. Deklaracja klasy 5VWFGPV składającej się z części publicznej i prywatnej mo e
                 wyglądać następująco:
                   ENCUU 5VWFGPV
                   ]
                     RWDNKE
                       XQKF ,CMK5VWFGPV
EJCT
XQKF +PKELCNKCELC

                       XQKF (KPCNKCELC

                     RTKXCVG
                       EJCT
0CYKUMQ
                   _

                 W sekcji publicznej (rozpoczynającej się od słowa kluczowego RWDNKE) deklaracji
                 klasy 5VWFGPV umieściliśmy prototypy trzech funkcji składowych klasy. W sekcji
                 prywatnej (rozpoczynającej się od słowa kluczowego RTKXCVG) umieściliśmy deklarację

2
    Jako ciekawostkę podajmy, i w latach 70. XX wieku słowo obiekt uto samiano z pewnym wydzielonym
    obszarem pamięci w du ych maszynach cyfrowych oraz innych maszynach zwanych mini- i mikrokomputerami.
    W takim znaczeniu słowa obiekt u ywali Brian Kernighan i Dennis Ritchie — twórcy języka C.
24                                                                   C++Builder 6. Ćwiczenia


       jednej zmiennej (dokładniej — wskaźnika) składowej klasy. Mimo e istnieje
       mo liwość deklarowania zmiennych publicznych w klasie, to jednak zalecane jest,
       aby ich deklaracje były umieszczane w sekcji prywatnej, zaś dostęp do nich był
       mo liwy poprzez funkcje z sekcji publicznej. Jak ju się zapewne domyślasz, dostęp
       do wskaźnika 0CYKUMQ z sekcji prywatnej będzie mo liwy właśnie poprzez funkcję
       ,CMK5VWFGPV
, której jedynym parametrem jest wskaźnik. Tego typu technika
       programowania nosi nazwę enkapsulacji danych, co oznacza, e dostęp do prywatnych
       danych jest zawsze ściśle kontrolowany.
     2. Jak się zapewne domyślasz, rolą bezparametrowej funkcji +PKELCNKCELC
 będzie
        zainicjowanie danych. Poniewa omawiana funkcja jest częścią klasy 5VWFGPV, to przy
       jej zapisie w programie musimy poinformować kompilator, i właśnie do niej nale y.
       Operator rozró niania zakresu  (ang. scope resolution operator) słu y temu celowi.
         XQKF 5VWFGPV+PKELCNKCELC

         ]
          0CYKUMQ  PGY EJCT=?
          EQWV  2T[FKGNQPQ RCOKúè 
          EQWV  GPFN  0CEK PKL 'PVGT  GPFN
          IGVEJCT

          TGVWTP
         _

       Jedyną rolą funkcji +PKELCNKCELC
 jest dynamiczne przydzielenie pamięci do
       wskaźnika 0CYKUMQ przy pomocy operatora PGY. Tekst wyświetlany jest jedynie
       w celach poglądowych.
     3. Funkcja (KPCNKCELC
 zajmuje się zwolnieniem przy pomocy operatora FGNGVG
       uprzednio przydzielonej pamięci.
         XQKF 5VWFGPV(KPCNKCELC

         ]
          FGNGVG=? 0CYKUMQ
          EQWV  YQNPKQPQ RCOKúè 
          EQWV  GPFN  0CEK PKL 'PVGT  GPFN
          TGVWTP
         _

     4. W funkcji ,CMK5VWFGPV
 dokonujemy porównania dwóch ciągów znaków. Przy
        pomocy funkcji UVTEOR
 z modułu UVTKPIJ porównujemy dwa łańcuchy znaków,
        czyli łańcuch wskazywany przez 0CYKUMQ oraz drugi, odpowiadający ju konkretnemu
        nazwisku danej osoby. Je eli oba łańcuchy są identyczne, funkcja UVTEOR
 zwraca
        wartość , zaś następnie przy pomocy strumienia wyjściowego EQWV wyświetlany
       jest odpowiedni komunikat.
         XQKF 5VWFGPV,CMK5VWFGPV
EJCT
U
         ]
           0CYKUMQ  U
           KH
UVTEOR
0CYKUMQ 9CEMQYUMK 
             UVTER[
0CYKUMQ DCTFQ FQDT[ UVWFGPV 
           KH
UVTEOR
0CYKUMQ ,CPMQYUMK 
              UVTER[
0CYKUMQ MKGRUMK UVWFGPV 
           EQWV  0CYKUMQ  GPFN  GPFN
           TGVWTP
         _
Rozdział 2.   C++ w pigułce                                                                      25


              5. W głównej funkcji OCKP
 wywołamy opisane wcześniej elementy klasy 5VWFGPV.
                  KPV OCKP

                  ]
                  EJCT
-VQT[5VWFGPV
                  -VQT[5VWFGPV  PGY EJCT=?
                  5VWFGPV +PHQ5VWFGPV
                  ENTUET

                  EQWV  2QFCL PCYKUMQ 
                  IGVU
-VQT[5VWFGPV
                  +PHQ5VWFGPV+PKELCNKCELC

                  +PHQ5VWFGPV,CMK5VWFGPV
-VQT[5VWFGPV
                  +PHQ5VWFGPV(KPCNKCELC

                  IGVEJ

                  FGNGVG=? -VQT[5VWFGPV
                  TGVWTP 
                 _

                I tak, w linii 3. deklarujemy wskaźnik -VQT[5VWFGPV przechowujący wpisywane
                z klawiatury nazwisko (dokładniej — wskazujący na pierwszą literę nazwiska), zaś
                w linii 4. przydzielamy mu przy pomocy operatora PGY odpowiedni obszar pamięci.
                W linii 5. deklarujemy egzemplarz +PHQ5VWFGPV klasy 5VWFGPV. W liniach 6. – 8.
                wczytujemy nazwisko studenta. Poniewa u ywamy wskaźnika, wygodniej jest
                w tym celu wykorzystać funkcję IGVU
, której prototyp znajduje się w pliku stdio.h.
                W liniach 10. i 11. w odpowiedniej kolejności wywołujemy funkcje składowe
                egzemplarza +PHQ5VWFGPV klasy 5VWFGPV. Aby wywołać funkcję składową egzemplarza
                klasy z fragmentu programu nie nale ącego do klasy (w naszym przypadku z głównej
                funkcji OCKP
), nale y w kolejności podać: nazwę egzemplarza klasy, operator
                w postaci kropki, zaś po nim nazwę właściwej funkcji. W linii 13. zwalniamy pamięć
                przydzieloną wskaźnikowi -VQT[5VWFGPV.
                Kompletny kod modułu Unit05.cpp projektu Projekt_05.bpr korzystającego z omawianej
                klasy przedstawiono na wydruku 2.5, zaś na rysunku 2.4 pokazano efekt naszej pracy.

Wydruk 2.5. Kod modułu Unit05.cpp
               KPENWFG KQUVTGCOJ
               KPENWFG UVTKPIJ
               KPENWFG EQPKQJ
               KPENWFG UVFKQJ
               RTCIOC JFTUVQR
              ENCUU 5VWFGPV
              ]
                RTKXCVG
                  EJCT
0CYKUMQ
                RWDNKE
                  XQKF ,CMK5VWFGPV
EJCT
XQKF +PKELCNKCELC

                  XQKF (KPCNKCELC

              _ +PHQ5VWFGPV
              
              XQKF 5VWFGPV+PKELCNKCELC

              ]
               0CYKUMQ  PGY EJCT=?
               EQWV  2T[FKGNQPQ RCOKúè 
               EQWV  GPFN  0CEK PKL 'PVGT  GPFN
26                                                                        C++Builder 6. Ćwiczenia


             IGVEJCT

             TGVWTP
            _
            
            XQKF 5VWFGPV(KPCNKCELC

            ]
             FGNGVG=? 0CYKUMQ
             EQWV  YQNPKQPQ RCOKúè 
             EQWV  GPFN  0CEK PKL 'PVGT  GPFN
             TGVWTP
            _
            
            XQKF 5VWFGPV,CMK5VWFGPV
EJCT
U
            ]
              0CYKUMQ  U
              KH
UVTEOR
0CYKUMQ 9CEMQYUMK 
                UVTER[
0CYKUMQ DCTFQ FQDT[ UVWFGPV 
              KH
UVTEOR
0CYKUMQ ,CPMQYUMK 
                 UVTER[
0CYKUMQ MKGRUMK UVWFGPV 
              EQWV  0CYKUMQ  GPFN  GPFN
              TGVWTP
            _
            
            KPV OCKP

            ]
              EJCT
-VQT[5VWFGPV
              -VQT[5VWFGPV  PGY EJCT=?
              5VWFGPV +PHQ5VWFGPV
              ENTUET

              EQWV  2QFCL PCYKUMQ 
              IGVU
-VQT[5VWFGPV
              +PHQ5VWFGPV+PKELCNKCELC

              +PHQ5VWFGPV,CMK5VWFGPV
-VQT[5VWFGPV
              +PHQ5VWFGPV(KPCNKCELC

              IGVEJ

              FGNGVG=? -VQT[5VWFGPV
              TGVWTP 
            _


Rysunek 2.4.
Projekt Projekt_05.bpr
w trakcie działania
Rozdział 2.    C++ w pigułce                                                                            27



Konstruktor i destruktor
              Przedstawiony na przykładzie projektu Projekt_05.bpr sposób inicjowania i finalizowania
              działania ró nych obiektów (w tym egzemplarzy klas) jest obecnie rzadko wykorzystywany
              w praktyce (poza zupełnie szczególnymi przypadkami, w których mamy jakieś konkretne
              wymagania odnośnie działania programu). Poniewa konieczność inicjalizowania (i ew.
              finalizowania) np. egzemplarzy klas w C++ występuje bardzo często, dlatego w praktyce
              wykorzystujemy automatyczną ich inicjalizację (i ew. finalizację). Tego rodzaju automaty-
              zacja mo liwa jest dzięki wykorzystaniu specjalnych funkcji składowych klasy zwanych
              konstruktorami. Konstruktor i destruktor zawsze posiadają taką samą nazwę jak klasa,
              do której nale ą. Ró nica w ich zapisie polega na tym, e nazwa destruktora poprzedzona
              jest znakiem `.

Ćwiczenie 2.8.

              Zmodyfikujemy poprzedni program w taki sposób, aby klasa 5VWFGPV posiadała swój kon-
              struktor i destruktor.
               1. Po wprowadzeniu konstruktora i destruktora do klasy 5VWFGPV, jej definicja przybierze
                 następującą postać:
                   ENCUU 5VWFGPV
                   ]
                     RWDNKE
                       XQKF ,CMK5VWFGPV
EJCT
5VWFGPV
  MQPUVTWMVQT
                       `5VWFGPV
 FGUVTWMVQT
                     RTKXCVG
                       EJCT
0CYKUMQ
                   _

                 Natychmiast zauwa ymy, i w C++ nie określa się typów powrotnych konstruktorów
                 i destruktorów, gdy z zało enia nie mogą zwracać adnych wartości.
               2. Zrozumienie idei u ywania konstruktorów i destruktorów ułatwi nam prześledzenie
                 poni szego wydruku.

Wydruk 2.6. Kod modułu Unit06.cpp projektu Projekt_06.bpr wykorzystującego funkcje składowe w postaci
konstruktora i destruktora klasy
                 KPENWFG KQUVTGCOJ
                 KPENWFG UVTKPIJ
                 KPENWFG EQPKQJ
                 KPENWFG UVFKQJ
                 RTCIOC JFTUVQR

               ENCUU 5VWFGPV
               ]
                 RWDNKE
                   XQKF ,CMK5VWFGPV
EJCT
5VWFGPV
  MQPUVTWMVQT
                   `5VWFGPV
 FGUVTWMVQT
                 RTKXCVG
                   EJCT
0CYKUMQ
               _
28                                                                      C++Builder 6. Ćwiczenia


      MQPUVTWMVQT MNCU[ 5VWFGPV
      5VWFGPV5VWFGPV

      ]
       0CYKUMQ  PGY EJCT=?
       EQWV  -QPUVTWMVQT MNCU[ QUVC CKPKELQYCP[ 
       EQWV  GPFN  0CEK PKL 'PVGT  GPFN
       IGVEJCT

      _
      
      XQKF 5VWFGPV,CMK5VWFGPV
EJCT
U
      ]
        0CYKUMQ  U
        KH
UVTEOR
0CYKUMQ 9CEMQYUMK 
          UVTER[
0CYKUMQ DCTFQ FQDT[ UVWFGPV 
        KH
UVTEOR
0CYKUMQ ,CPMQYUMK 
           UVTER[
0CYKUMQ MKGRUMK UVWFGPV 
        EQWV  0CYKUMQ  GPFN

        EQWV  GPFN 0CEK PKL MNCYKU  GPFN
        TGVWTP
      _
      FGUVTWMVQT MNCU[ 5VWFGPV
      5VWFGPV`5VWFGPV

      ]
        FGNGVG=? 0CYKUMQ
        EQWV  -QPUVTWMVQT QUVC PKUEQP[
                 2QYVÎTPKG PCEK PKL MNCYKU  GPFN
        IGVEJ

      _
      
      KPV OCKP

      ]
        EJCT
-VQT[5VWFGPV
        -VQT[5VWFGPV  PGY EJCT=?
        5VWFGPV +PHQ5VWFGPV
        ENTUET

        EQWV  2QFCL PCYKUMQ 
        IGVU
-VQT[5VWFGPV
        +PHQ5VWFGPV,CMK5VWFGPV
-VQT[5VWFGPV
        IGVEJ

        FGNGVG=? -VQT[5VWFGPV
        TGVWTP 
      _


     Uruchamiając program bez trudu przekonamy się, i konstruktor 5VWFGPV
 jest automa-
     tycznie uruchamiany podczas tworzenia egzemplarza klasy, czyli w momencie wykonywania
     instrukcji deklarującej egzemplarz klasy. Jest to jedna z cech odró niających język C++ od
     zwykłego C. W C++ deklaracje zmiennych wykonywane są w trakcie działania programu.

     Ze względu na to, e ka dy egzemplarz klasy jest tworzony w trakcie wykonywania in-
     strukcji jego deklaracji, musi on być niszczony automatycznie w trakcie opuszczania bloku
     programu, w którym powy sza deklaracja się znajduje. Testując projekt Projekt_06.bpr
     bez trudu przekonamy się, i mimo e destruktor `5VWFGPV
 nie został jawnie wywołany,
     to jednak kod jego zostanie wykonany, zwalniając tym samym pamięć przydzieloną uprzed-
     nio wskaźnikowi 0CYKUMQ przez konstruktor 5VWFGPV
.
Rozdział 2.    C++ w pigułce                                                                          29



Ćwiczenie 2.9.

              Samodzielnie przetestuj projekty Projekt_05.bpr oraz Projekt_06.bpr pod kątem okre-
              ślenia ró nic w działaniu zwykłych funkcji składowych +PKELCNKCELC
 i (KPCNKCELC

              oraz konstruktora 5VWFGPV
 i destruktora `5VWFGPV
.

Ćwiczenie 2.10.

              Często, w celu uczynienia programu bardziej przejrzystym, definicje klas umieszczamy
              w oddzielnym pliku nagłówkowym. Postaraj się samodzielnie stworzyć taki plik i włączyć
              go do programu.



Inne spojrzenie na klasy. Własności
              C++Builder, jako kompletne środowisko programowania, wprowadza bardziej ogólne
              pojęcie klasy. Otó w Builderze definicję klasy mo na znacznie wzbogacić, tzn. w skład
              tej definicji oprócz sekcji prywatnej i publicznej mo e wchodzić równie sekcja publi-
              kowana (ang. published) rozpoczynająca się od słowa kluczowego AARWDNKUJGF. W tej
              sekcji umieszcza się z reguły deklaracje funkcji, czyli deklaracje metod związane z kom-
              ponentami pochodzącymi z biblioteki VCL. Dodatkowo klasa mo e zawierać te definicje
              własności rozpoczynające się od słowa AARTQRGTV[. Warto w tym miejscu zauwa yć, i
              definicje w klasie związane z biblioteką VCL będą rozpoczynać się od pewnych słów
              kluczowych, poprzedzonych podwójnym znakiem podkreślenia. Chocia do klas związanych
              z biblioteką komponentów wizualnych powrócimy jeszcze w dalszej części ksią ki, to jednak
              w tym miejscu poka emy, w jaki sposób mo na zbudować prostą własność w klasie.

Ćwiczenie 2.11.

              Zbudujemy prostą klasę, której wykorzystanie w programie umo liwi w sposób bardzo
              elegancki i przejrzysty odczytywanie i zapisywanie danych w postaci nazwisk wybranych
              osób. W tym celu skorzystamy z definicji własności. Poniewa ogólnie przyjętą konwencją
              jest to, aby w tego typu programach posługiwać się pewnymi standardowymi przedrostkami
              dla zmiennych oraz funkcji, w dalszej części opisu będziemy wykorzystywać nazewnictwo
              angielskie — po to, by nie tworzyć mieszanki nazw polskich i angielskich (np. 5GV0CYKUMQ).
               1. Na potrzeby naszego ćwiczenia samodzielnie zbudujemy własność, przy pomocy
                  której będziemy w stanie odczytywać i przypisywać odpowiednie wartości (w tym
                  przypadku łańcuchy znaków reprezentujące nazwiska i imiona osób). Ka da własność
                  słu y do przechowywania wartości, zatem nale y zadeklarować związaną z nią zmienną
                  (tzw. pole w klasie). Ogólnie przyjętą konwencją jest to, e zmienne mają takie same
                  nazwy, jak związane z nimi własności, ale poprzedzone są literą (. W naszym
                  programie w sekcji prywatnej definicji klasy 5VWFGPVU zadeklarujemy jedną taką
                  zmienną typu #PUK5VTKPI, reprezentującą tablicę indeksującą nazwiska studentów.
                  Dodatkowo w tej samej sekcji zadeklarujemy dwie funkcje (metody): )GV0COG
,
                  która w przyszłości będzie odczytywała przy pomocy indeksu imię i nazwisko wybranej
                  osoby oraz 5GV0COG
, za pomocą której będzie mo na przypisać odpowiedni łańcuch
                  znaków (imię i nazwisko) do odpowiedniego indeksu w tablicy.
30                                                                            C++Builder 6. Ćwiczenia


                RTKXCVG
                   #PUK5VTKPI (0COG=?
                   #PUK5VTKPI )GV0COG
KPV KPFGZ
                   XQKF 5GV0COG
KPV #PUK5VTKPI

            2. Przechodzimy teraz do deklaracji samej własności. W tym celu nale y u yć słowa
               kluczowego AARTQRGTV[. Dla naszych potrzeb wystarczy, by własność słu yła
              wyłącznie do przekazywania danych (imion i nazwisk osób) przy pomocy indeksu.
              Własność zadeklarujemy w sekcji publicznej definicji klasy. Zdefiniowana przez nas
              własność 0COG będzie odczytywać aktualny stan tablicy (0COG przy pomocy dyrektywy
              TGCF, a następnie przekazywać (zapisywać) ją do funkcji 5GV0COG
 korzystając
              z dyrektywy YTKVG.
                RWDNKE
                   5VWFGPVU
]_  MQPUVTWMVQT
                   `5VWFGPVU
]_  FGUVTWMVQT
                   AARTQRGTV[ #PUK5VTKPI 0COG=KPV KPFGZ? 
                                             ]TGCF)GV0COG YTKVG5GV0COG_

            3. Jednoparametrowa funkcja (metoda) )GV0COG
 ma bardzo prostą budowę i słu yć
              będzie do odpowiedniego indeksowania nazwisk:
                #PUK5VTKPI 5VWFGPVU)GV0COG
KPV K
                ]
                  TGVWTP (0COG=K?
                _

            4. Dwuparametrowa funkcja (metoda) 5GV0COG
 równie nie jest skomplikowana
               i przypisuje odpowiedniemu indeksowi tablicy ciąg znaków określony przez PCOGU.
                XQKF 5VWFGPVU5GV0COG
KPV K EQPUV #PUK5VTKPI PCOGU
                ]
                   (0COG=K?PCOGU
                _

              Kompletny kod modułu Unit_07.cpp projektu Projekt_07.bpr wykorzystującego
              własność w klasie pokazany jest na wydruku 2.7.

Wydruk 2.7. Moduł Unit07.cpp
             KPENWFG XENJ
             KPENWFG UVFKQJ
             KPENWFG EQPKQJ
             RTCIOC JFTUVQR

            ENCUU 5VWFGPVU
            ]
             RWDNKE
               5VWFGPVU
]_  MQPUVTWMVQT MNCU[
               `5VWFGPVU
]_  FGUVTWMVQT MNCU[
               AARTQRGTV[ #PUK5VTKPI 0COG=KPV KPFGZ? 
                                         ]TGCF)GV0COG YTKVG5GV0COG_
             RTKXCVG
               #PUK5VTKPI (0COG=?
               #PUK5VTKPI )GV0COG
KPV KPFGZ
               XQKF 5GV0COG
KPV #PUK5VTKPI
            _ 2GTUQP GIGORNCT 2GTUQP 
QUQDC MNCU[ 5VWFGPVU
Rozdział 2.    C++ w pigułce                                                                        31


               #PUK5VTKPI 5VWFGPVU)GV0COG
KPV K
               ]
                 TGVWTP (0COG=K?
               _
               
               XQKF 5VWFGPVU5GV0COG
KPV K EQPUV #PUK5VTKPI PCOGU
               ]
                  (0COG=K?PCOGU
               _
               
               KPV OCKP

               ]
                 ENTUET

                 2GTUQP0COG=? 9CEGM ,CPMQYUMK   Y[YQ WLG 2GTUQP5GV0COG

                 2GTUQP0COG=? ,CPGM 9CEMQYUMK 
                 2GTUQP0COG=? ,QNC .QDWKPUMC 

                  HQT 
KPV K   K   K


                    RWVU
2GTUQP0COG=K?EAUVT
  Y[YQ WLG 2GTUQP)GV0COG

                IGVEJ

                TGVWTP 
               _


              W głównej funkcji programu, w celu wyświetlenia odpowiednich łańcuchów znaków,
              u yliśmy metody EAUVT
 zwracającej wskaźnik (EJCT
) do pierwszego znaku łańcucha
              identyfikującego własność tablicową 0COG egzemplarza 2GTUQP klasy 5VWFGPVU. Mo na
              te zauwa yć, i u ycie w programie słowa AARTQRGTV[ oraz typu #PUK5VTKPI (elementy
              te nie są zdefiniowane w standardowym C++) wymaga włączenia do kodu modułu pliku
              nagłówkowego vcl.h (patrz rysunek 2.1).




Funkcje przeładowywane
              Stosowanie w programie funkcji przeładowywanych (często te nazywanych funkcjami
              przecią anymi) w bardzo wielu wypadkach mo e znacznie ułatwić pisanie rozbudowa-
              nych programów. U ywanie funkcji przeładowywanych nierozerwalnie wią e się z tzw.
              polimorfizmem w C++. Polega on na zdefiniowaniu większej liczby funkcji posiadających
              taką samą nazwę, ale o ró nych postaciach listy parametrów. Mo liwość przecią ania
              funkcji jest w C++ czymś bardzo naturalnym i nie wymaga stosowania w ich deklaracjach
              specjalnych dyrektyw. Dla porównania przypomnijmy, e w Delphi funkcje czy procedury
              przecią ane zawsze nale y deklarować z dyrektywą QXGTNQCF. Pod względem u ywania
              funkcji przeładowywanych C++ nie generuje adnego nadmiarowego kodu w porównaniu
              z Object Pascalem.

Ćwiczenie 2.12.

              Stworzymy program obliczający kolejne całkowite potęgi liczb ró nych typów.
               1. Program zawierać będzie dwie podobne (ale nie takie same) funkcje o nazwie
                  RQYGT
 (potęga), zwracające kolejne potęgi pobranego argumentu. Prototypy tych
                  funkcji mo emy zapisać w sposób następujący:
32                                                                            C++Builder 6. Ćwiczenia


                WPUKIPGF KPV RQYGT
WPUKIPGF KPV Z WPUKIPGF KPV [
                FQWDNG RQYGT
FQWDNG FZ WPUKIPGF NQPI F[

            2. Następnie zapiszmy ciała tych funkcji:
                WPUKIPGF KPV RQYGT
WPUKIPGF KPV Z WPUKIPGF KPV [
                ]
                  WPUKIPGF KPV K 
                  HQT
K K[ K
Z
                  TGVWTP 
                _
                
                FQWDNG RQYGT
FQWDNG FZ WPUKIPGF NQPI F[
                ]
                  FQWDNG 
                  HQT
WPUKIPGF KPV K KF[ K
FZ
                  TGVWTP 
                _

              Jak widać, nazwa RQYGT
 nie oznacza adnej konkretnej funkcji, a jedynie ogólny
              rodzaj działania wykonywanego na konkretnym typie liczb.
            3. Wybór wersji funkcji odpowiadającej określonym potrzebom programisty jest
              wykonywany automatyczne przez kompilator, dzięki podaniu typu parametrów
              aktualnych wywoływanej funkcji RQYGT
. Czynność tę wykonujemy wywołując
              odpowiednie funkcje w programie głównym.
                KPV OCKP

                ]
                  ENTUET

                  HQT
WPUKIPGF KPV   K K K


                    EQWV GPFN     @ K   RQYGT
 K
                  EQWV GPFN
                  HQT
WPUKIPGF KPV   K K K


                    EQWV GPFN     @ K   RQYGT
 K


                    EQWV  GPFN  0CEK PKL MNCYKU 
                    IGVEJ

                    TGVWTP 
                _

              Jak łatwo zauwa yć, główną zaletą przeładowywania funkcji jest to, e bez problemu
              mo na wywoływać powiązane ze sobą zestawy instrukcji za pomocą tej samej nazwy,
              co pozwala, tak jak w pokazanym przypadku, zredukować dwie nazwy do jednej.
              Kompletny kod źródłowy głównego modułu projektu Projekt_08.bpr,
              wykorzystującego przeładowywane funkcje, zamieszczono na wydruku 2.8.

Wydruk 2.8. Moduł Unit08.cpp
             KPENWFG KQUVTGCOJ
             KPENWFG EQPKQJ
             RTCIOC JFTUVQR
            RTQVQV[R[ RTG CFQY[YCPGL HWPMELK RQYGT

            WPUKIPGF KPV RQYGT
WPUKIPGF KPV Z WPUKIPGF KPV [
            FQWDNG RQYGT
FQWDNG FZ WPUKIPGF NQPI F[
Rozdział 2.    C++ w pigułce                                                                    33


               KPV OCKP

               ]
                 ENTUET

                 HQT
WPUKIPGF KPV   K K K


                   EQWV GPFN     @ K   RQYGT
 K
                 EQWV GPFN
                 HQT
WPUKIPGF KPV   K K K


                   EQWV GPFN     @ K   RQYGT
 K


                  EQWV  GPFN  0CEK PKL MNCYKU 
                  IGVEJ

                  TGVWTP 
               _
               
               WPUKIPGF KPV RQYGT
WPUKIPGF KPV Z WPUKIPGF KPV [
               ]
                 WPUKIPGF KPV K 
                 HQT
K K[ K
Z
                 TGVWTP 
               _
               
               FQWDNG RQYGT
FQWDNG FZ WPUKIPGF NQPI F[
               ]
                 FQWDNG 
                 HQT
WPUKIPGF KPV K KF[ K
FZ
                 TGVWTP 
               _


              Kończąc rozwa ania o funkcjach przeładowywanych nale y zauwa yć, i teoretycznie
              mo emy nadawać identyczne nazwy funkcjom wykonującym ró ne działania, np. mno-
               enie, potęgowanie i logarytmowanie. Jednak z praktycznego punktu widzenia nie po-
              winniśmy postępować w ten sposób. Zawsze nale y dą yć do tego, aby przeładowywać
              funkcje wykonujące te same operacje.

Ćwiczenie 2.13.

              Postaraj się zmodyfikować Projekt_08.bpr w taki sposób, aby bazował na pewnej klasie
              wykorzystującej omawiane funkcje.



Niejednoznaczność
              Polimorfizm, którego przykładem jest mo liwość przeładowywania funkcji, stanowi jedną
              z wielkich zalet obiektowego języka C++, jednak równie niesie ze sobą (szczególnie
              dla mniej doświadczonych programistów) pewne pułapki. Jedną z nich jest niejedno-
              znaczność. Głównym źródłem niejednoznaczności w C++ są automatyczne konwersje
              typów. Uwa ny Czytelnik na pewno spostrzegł, w jaki sposób w programie przedstawionym
              na wydruku 2.8 wywoływane są funkcje nale ące do swoich prototypów:
34                                                                        C++Builder 6. Ćwiczenia


      WPUKIPGF KPV RQYGT
WPUKIPGF KPV Z WPUKIPGF KPV [  RTQVQV[R
      HQT
WPUKIPGF KPV K K K


          EQWV GPFN  @ K   RQYGT
 K
                                        Y[YQ CPKG Y RTQITCOKG

     oraz:
      FQWDNG RQYGT
FQWDNG FZ WPUKIPGF NQPI F[  RTQVQV[R
      HQT
WPUKIPGF KPV K K K


          EQWV GPFN  @ K   RQYGT
 K

                                        Y[YQ CPKG Y RTQITCOKG

     Funkcja RQYGT
 została przeładowana w taki sposób, e mo e pobierać argumenty w postaci
     par liczb typu WPUKIPGF KPV, WPUKIPGF KPV oraz FQWDNG, WPUKIPGF NQPI. Pierwsza instruk-
     cja wywołania funkcji RQYGT
 będzie jednoznaczna, gdy nie musi występować adna
     konwersja danych pomiędzy jej parametrami formalnymi i aktualnymi. Rozpatrzmy przy-
     padek, gdy funkcja RQYGT
 wywoływana jest z parametrem typu całkowitego WPUKIPGF
     KPV, będącego typem zmiennej sterującej K w pętli HQT
, zaś jednym z jej parametrów
     formalnych (zdeklarowanym w jej prototypie) jest zmienna typu WPUKIPGF NQPI. W takiej
     sytuacji kompilator „nie wie”, czy zmienną taką przekształcić na typ NQPI KPV, czy NQPI
     FQWDNG. Je eli wywołalibyśmy funkcję w programie w sposób następujący:
      HQT
WPUKIPGF KPV K K K


          EQWV GPFN  @ K   RQYGT
 K
                                         D úFPG Y[YQ CPKG Y RTQITCOKG

     mo emy spodziewać się wystąpienia przykrego komunikatu kompilatora:
      =%

 'TTQT? 7PKVERR
 ' #ODKIWKV[ DGVYGGP RQYGT
WPUKIPGF KPVWPUKIPGF KPV
      CPF RQYGT
FQWDNGWPUKIPGF NQPI

     Aby uniknąć tego typu dwuznaczności, często uciekamy się do pewnego fortelu. Mianowicie
     wystarczy do liczby deklarowanej jako całkowita dodać wartość , aby kompilator do-
     konał jej automatycznej konwersji na typ zmiennopozycyjny.




Funkcje ogólne
     Funkcjami ogólnymi posługujemy się w sytuacjach, w których wymagamy, aby definicja
     danej funkcji zawierała całość operacji wykonywanych na danych ró nych typów. Funkcję
     ogólną tworzymy przy pomocy słowa kluczowego VGORNCVG (szablon). Jego intuicyjne
     znaczenie jest bardzo trafne — szablon słu y do ogólnego opisu działań wykonywanych
     przez daną funkcję, zaś dalszymi szczegółami powinien zająć się ju sam kompilator
     C++. Szkielet definicji funkcji ogólnej rozpoczyna się właśnie od słowa VGORNCVG:
      VGORNCVG ENCUU 6[RCP[EJ 6[RYTCECP[ 0CYC(WPMELK
NKUVC RCTCOGVTÎY
      ]
         KPUVTWMELG
      _
Rozdział 2.    C++ w pigułce                                                                         35


Ćwiczenie 2.14.

              Jak zapewne wiesz, jedną z właściwości języków C i C++ jest to, i wszystkie argumenty
              funkcji przekazywane są przez wartość. Wynika z tego, e wywoływana funkcja otrzymuje
              wartości swoich argumentów, a nie ich adresy. Mo na oczywiście spowodować, aby funkcja
              zmieniała wartości zmiennych w funkcji wywołującej. W tym celu funkcja wywołująca musi
              przekazać adresy swoich zmiennych. Zbudujemy prostą funkcję ogólną, która zmieniać
              będzie wartości dwóch zmiennych przekazywanych jej w instrukcji wywołania. Funkcja
              będzie porównywać dwie zmienne i jako wartość powrotną zwracać większą z liczb.
               1. Zadeklarujemy prostą funkcję ogólną o nazwie OCZ
.
                   VGORNCVG ENCUU 6 6 OCZ
6 Z 6 [
                   ]
                     TGVWTP 
Z [ ! Z  [
                   _

                  Litera 6 oznacza tutaj nazwę zastępczą typu danych wykorzystywanych przez
                  dwuparametrową funkcją OCZ
. Zaletą podawania nazwy zastępczej jest to,
                   e kompilator zawsze automatycznie zastąpi ją rzeczywistym typem danych
                  w trakcie tworzenia konkretnej wersji funkcji. W funkcji tej wykorzystaliśmy
                  operator warunkowy ! (pytajnik i dwukropek). Znaczenie jego jest następujące:
                   ' ! '  '

                  Je eli wartość logiczna wyra enia (lub warunku) ' występującego po lewej stronie
                  znaku ! jest prawdą (wartość ró na od zera), wówczas funkcja zwróci wartość wyra enia
                  ' (w naszym przypadku Z), w przeciwnym razie wartością powrotną funkcji będzie
                  wartość wyra enia ' występującego po znaku  (w naszym przypadku [).
               2. Wywołanie funkcji ogólnej OCZ
 w programie głównym nie powinno sprawić nam
                  najmniejszych trudności. Na wydruku 2.9 pokazano kompletny kod źródłowy modułu
                  Unit09.cpp projektu Projekt_09.bpr.

Wydruk 2.9. Moduł Unit09.cpp
                KPENWFG KQUVTGCOJ
                KPENWFG EQPKQJ
                RTCIOC JFTUVQR
               VGORNCVG ENCUU 6 6 OCZ
6 Z 6 [
               ]
                 TGVWTP 
Z [ ! Z  [
               _
               
               KPV OCKP

               ]
                 FQWDNG Z [
                 EQWVUGVH
KQUHKZGF
                 EQWV  OCZ
Z [  GPFN
                 IGVEJ

                 TGVWTP 
               _
36                                                                               C++Builder 6. Ćwiczenia


           W programie występuje dodatkowy szczegół, na który warto zwrócić uwagę. Mianowicie
           sposób formatowania liczb. W celu wyświetlenia wartości z większą liczbą cyfr po kropce,
           oddzielającej część całkowitą od części ułamkowej, wykorzystaliśmy metodę UGVH strumie-
           nia EQWV oraz metodę HKZGF (zwaną tutaj manipulatorem) klasy KQU. Z innymi sposobami
           przedstawiania liczb z u yciem funkcji składowych klasy KQU mo emy zapoznać się studiując
           pliki pomocy.

Ćwiczenie 2.15.

           Programiści C przyzwyczajeni są do u ywania makrodefinicji. Definicję funkcji ogólnej
           OCZ
 mo emy zastąpić następującą makrodefinicją:
              FGHKPG OCZ
Z [ 

Z      [ ! Z  [

           Warto jednak zwrócić uwagę, i makrodefinicje nie mogą zmieniać wartości swoich pa-
           rametrów. Z tego względu pokazany sposób tworzenia makrodefinicji OCZ
 uwa a się
           obecnie za przestarzały. Programy tworzone w „czystym” C++ powinny (o ile jest to
           konieczne) u ywać funkcji ogólnych, umo liwiających operowanie na ró nych typach
           parametrów. Przetestuj samodzielnie projekt Projekt_09.bpr wykorzystując opisaną ma-
           krodefinicję.



Przeładowywanie funkcji ogólnych
           Z potrzebą przeładowywania funkcji ogólnych mo emy spotkać się w sytuacji, w której
           istnieje konieczność zbudowania funkcji przeładowującej funkcję ogólną do określonego
           zestawu typów parametrów formalnych.

Ćwiczenie 2.16.

           Jako prostą ilustrację metody przeładowania omawianej wcześniej funkcji ogólnej OCZ

           niech nam posłu y przykład, w którym za ądamy, aby wartością powrotną funkcji przeła-
           dowującej była mniejsza z dwu liczb całkowitych będących jej argumentami.
             1. Jawne przeładowanie funkcji ogólnej OCZ
 mo e przybrać następującą postać:
                   VGORNCVG ENCUU 6 6 OCZ
6 Z 6 [
                   ]
                     TGVWTP 
Z [ ! Z  [
                   _
                   RTG CFQYCPC YGTULC HWPMELK QIÎNPGL OCZ

                   OCZ
KPV Z KPV [
                   ]
                     TGVWTP 
Z  [ ! Z  [
                   _

                  Cechą charakterystyczną przeładowywanych funkcji ogólnych jest to, e wszystkie
                  ich wersje muszą wykonywać identyczne działania, zaś ró nić się mogą jedynie
                  typami danych. Mogłoby się wydawać, e funkcja ogólna OCZ
 oraz jej wersja
                  przeładowana wykonują ró ne działania, jednak z numerycznego punktu widzenia tak
                  nie jest. Wynika to z faktu, i zarówno obliczanie większej, jak i mniejszej wartości

Mais conteúdo relacionado

Mais procurados

Programuje W Delphi I C Builder
Programuje W Delphi I C BuilderProgramuje W Delphi I C Builder
Programuje W Delphi I C BuilderGregory Grex
 
Programuje W Delphi I C Builder
Programuje W Delphi I C BuilderProgramuje W Delphi I C Builder
Programuje W Delphi I C Builderfreeebook
 
Flash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatceFlash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatceWydawnictwo Helion
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychWydawnictwo 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
 
Pajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznikPajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznikWydawnictwo Helion
 
C++. Styl i technika zaawansowanego programowania
C++. Styl i technika zaawansowanego programowaniaC++. Styl i technika zaawansowanego programowania
C++. Styl i technika zaawansowanego programowaniaWydawnictwo Helion
 
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2Wydawnictwo Helion
 
Adobe Creative Suite 2/2 PL. Oficjalny podręcznik
Adobe Creative Suite 2/2 PL. Oficjalny podręcznikAdobe Creative Suite 2/2 PL. Oficjalny podręcznik
Adobe Creative Suite 2/2 PL. Oficjalny podręcznikWydawnictwo Helion
 
Programuję W Delphi I C Builder
Programuję W Delphi I C BuilderProgramuję W Delphi I C Builder
Programuję W Delphi I C BuilderAdam
 
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
 
Microsoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga ekspertaMicrosoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga ekspertaWydawnictwo Helion
 
Photoshop CS2/CS2 PL. Prosto do celu
Photoshop CS2/CS2 PL. Prosto do celuPhotoshop CS2/CS2 PL. Prosto do celu
Photoshop CS2/CS2 PL. Prosto do celuWydawnictwo Helion
 
Adobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznikAdobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznikWydawnictwo Helion
 
C++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. PodstawyC++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. PodstawyWydawnictwo Helion
 
Adobe Illustrator 10. Ćwiczenia
Adobe Illustrator 10. ĆwiczeniaAdobe Illustrator 10. Ćwiczenia
Adobe Illustrator 10. ĆwiczeniaWydawnictwo Helion
 

Mais procurados (20)

Linux. Kurs. Wydanie II
Linux. Kurs. Wydanie IILinux. Kurs. Wydanie II
Linux. Kurs. Wydanie II
 
Programuje W Delphi I C Builder
Programuje W Delphi I C BuilderProgramuje W Delphi I C Builder
Programuje W Delphi I C Builder
 
Programuje W Delphi I C Builder
Programuje W Delphi I C BuilderProgramuje W Delphi I C Builder
Programuje W Delphi I C Builder
 
Flash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatceFlash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatce
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
 
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
 
Pajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznikPajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznik
 
C++. Styl i technika zaawansowanego programowania
C++. Styl i technika zaawansowanego programowaniaC++. Styl i technika zaawansowanego programowania
C++. Styl i technika zaawansowanego programowania
 
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
 
Adobe Creative Suite 2/2 PL. Oficjalny podręcznik
Adobe Creative Suite 2/2 PL. Oficjalny podręcznikAdobe Creative Suite 2/2 PL. Oficjalny podręcznik
Adobe Creative Suite 2/2 PL. Oficjalny podręcznik
 
Programuję W Delphi I C Builder
Programuję W Delphi I C BuilderProgramuję W Delphi I C Builder
Programuję W Delphi I C Builder
 
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
 
Microsoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga ekspertaMicrosoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga eksperta
 
Photoshop CS2/CS2 PL. Prosto do celu
Photoshop CS2/CS2 PL. Prosto do celuPhotoshop CS2/CS2 PL. Prosto do celu
Photoshop CS2/CS2 PL. Prosto do celu
 
Solid Edge 17. Podstawy
Solid Edge 17. PodstawySolid Edge 17. Podstawy
Solid Edge 17. Podstawy
 
C++. Sztuka programowania
C++. Sztuka programowaniaC++. Sztuka programowania
C++. Sztuka programowania
 
Adobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznikAdobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznik
 
C++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. PodstawyC++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. Podstawy
 
Adobe Illustrator 10. Ćwiczenia
Adobe Illustrator 10. ĆwiczeniaAdobe Illustrator 10. Ćwiczenia
Adobe Illustrator 10. Ćwiczenia
 

Destaque (13)

ABC tworzenia stron WWW
ABC tworzenia stron WWWABC tworzenia stron WWW
ABC tworzenia stron WWW
 
Windows XP PL. Ćwiczenia zaawansowane
Windows XP PL. Ćwiczenia zaawansowaneWindows XP PL. Ćwiczenia zaawansowane
Windows XP PL. Ćwiczenia zaawansowane
 
Tcl-Tk. Programowanie
Tcl-Tk. ProgramowanieTcl-Tk. Programowanie
Tcl-Tk. Programowanie
 
Protokoły SNMP i RMON. Vademecum profesjonalisty
Protokoły SNMP i RMON. Vademecum profesjonalistyProtokoły SNMP i RMON. Vademecum profesjonalisty
Protokoły SNMP i RMON. Vademecum profesjonalisty
 
Pamiętniki hakerów
Pamiętniki hakerówPamiętniki hakerów
Pamiętniki hakerów
 
Po prostu CorelDRAW 11
Po prostu CorelDRAW 11Po prostu CorelDRAW 11
Po prostu CorelDRAW 11
 
Java 2. Podstawy
Java 2. PodstawyJava 2. Podstawy
Java 2. Podstawy
 
Telefony komórkowe
Telefony komórkoweTelefony komórkowe
Telefony komórkowe
 
PHP. Programowanie
PHP. ProgramowaniePHP. Programowanie
PHP. Programowanie
 
Mandrake Linux. Ćwiczenia
Mandrake Linux. ĆwiczeniaMandrake Linux. Ćwiczenia
Mandrake Linux. Ćwiczenia
 
CorelDRAW 11. Ćwiczenia zaawansowane
CorelDRAW 11. Ćwiczenia zaawansowaneCorelDRAW 11. Ćwiczenia zaawansowane
CorelDRAW 11. Ćwiczenia zaawansowane
 
Efektywne programowanie w języku Java
Efektywne programowanie w języku JavaEfektywne programowanie w języku Java
Efektywne programowanie w języku Java
 
Odzyskiwanie danych w praktyce
Odzyskiwanie danych w praktyceOdzyskiwanie danych w praktyce
Odzyskiwanie danych w praktyce
 

Semelhante a C++Builder 6. Ćwiczenia

Język C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowaniaJęzyk C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowaniaWydawnictwo Helion
 
Visual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programistyVisual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programistyWydawnictwo Helion
 
C++Builder. Kompendium programisty
C++Builder. Kompendium programistyC++Builder. Kompendium programisty
C++Builder. Kompendium programistyWydawnictwo Helion
 
Programuje w Delphi i C Builder
Programuje w Delphi i C BuilderProgramuje w Delphi i C Builder
Programuje w Delphi i C BuilderEbooki za darmo
 
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
 
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
 
Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wydawnictwo Helion
 
C++. 50 efektywnych sposobów na udoskonalenie Twoich programów
C++. 50 efektywnych sposobów na udoskonalenie Twoich programówC++. 50 efektywnych sposobów na udoskonalenie Twoich programów
C++. 50 efektywnych sposobów na udoskonalenie Twoich programówWydawnictwo Helion
 
Adobe PageMaker 7.0. Oficjalny podręcznik
Adobe PageMaker 7.0. Oficjalny podręcznikAdobe PageMaker 7.0. Oficjalny podręcznik
Adobe PageMaker 7.0. Oficjalny podręcznikWydawnictwo Helion
 
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWydawnictwo Helion
 
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...Wydawnictwo Helion
 

Semelhante a C++Builder 6. Ćwiczenia (16)

Język C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowaniaJęzyk C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowania
 
Visual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programistyVisual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programisty
 
C++Builder. Kompendium programisty
C++Builder. Kompendium programistyC++Builder. Kompendium programisty
C++Builder. Kompendium programisty
 
Programuje w Delphi i C Builder
Programuje w Delphi i C BuilderProgramuje w Delphi i C Builder
Programuje w Delphi i C Builder
 
Uczta programistów
Uczta programistówUczta programistów
Uczta programistów
 
Visual Basic .NET. Ćwiczenia
Visual Basic .NET. ĆwiczeniaVisual Basic .NET. Ćwiczenia
Visual Basic .NET. Ć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
 
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
 
Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wstęp do programowania w języku C#
Wstęp do programowania w języku C#
 
C++. 50 efektywnych sposobów na udoskonalenie Twoich programów
C++. 50 efektywnych sposobów na udoskonalenie Twoich programówC++. 50 efektywnych sposobów na udoskonalenie Twoich programów
C++. 50 efektywnych sposobów na udoskonalenie Twoich programów
 
C++ bez obaw
C++ bez obawC++ bez obaw
C++ bez obaw
 
Adobe PageMaker 7.0. Oficjalny podręcznik
Adobe PageMaker 7.0. Oficjalny podręcznikAdobe PageMaker 7.0. Oficjalny podręcznik
Adobe PageMaker 7.0. Oficjalny podręcznik
 
ArchiCAD 10
ArchiCAD 10ArchiCAD 10
ArchiCAD 10
 
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
 
SolidWorks 2006 w praktyce
SolidWorks 2006 w praktyceSolidWorks 2006 w praktyce
SolidWorks 2006 w praktyce
 
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
 

Mais de 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
 
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
 
Serwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieSerwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieWydawnictwo Helion
 

Mais de 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
 
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
 
Serwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieSerwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanie
 

C++Builder 6. Ćwiczenia

  • 1. IDZ DO PRZYK£ADOWY ROZDZIA£ SPIS TRE CI C++Builder 6. Æwiczenia KATALOG KSI¥¯EK Autor: Andrzej Daniluk KATALOG ONLINE ISBN: 83-7197-986-X Format: B5, stron: 128 ZAMÓW DRUKOWANY KATALOG Przyk³ady na ftp: 1391 kB TWÓJ KOSZYK DODAJ DO KOSZYKA Borland C++ Builder to jedno z najwygodniejszych rodowisk programistycznych dla programistów C++, platforma ciesz¹ca siê du¿¹ popularno ci¹ i maj¹ca za sob¹ d³ug¹ historiê. W jêzyku C++ napisano wiele aplikacji dla Windows, z których znaczna czê æ CENNIK I INFORMACJE powsta³a w³a nie w Builderze. „C++ Builder. Æwiczenia” to uzupe³nienie poprzedniej publikacji Wydawnictwa Helion, ZAMÓW INFORMACJE zatytu³owanej „C++ Builder 5. Æwiczenia praktyczne”. Ksi¹¿ka omawia zmiany, jakie O NOWO CIACH wprowadzono w nowej, szóstej ju¿ wersji C++ Buildera, a tak¿e porusza wiele zagadnieñ, które nie znalaz³y siê w ksi¹¿ce traktuj¹cej o poprzedniej edycji tego ZAMÓW CENNIK programu. Informacje zosta³y przekazane w formie æwiczeñ z dok³adnym omówieniem prezentowanego kodu ród³owego. Znajdziesz w niej miêdzy innymi: CZYTELNIA • Zagadnienia zwi¹zane z kompatybilno ci¹ pomiêdzy wersjami pi¹t¹ i szóst¹ FRAGMENTY KSI¥¯EK ONLINE C++ Buildera • Seriê æwiczeñ przybli¿aj¹cych jêzyk C++ • Omówienie rodowiska IDE C++ Builder • Æwiczenia z programowania w C++ z wykorzystaniem C++ Builder • Æwiczenia z pisania aplikacji wielow¹tkowych • Sposoby tworzenia w³asnych komponentów Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: helion@helion.pl
  • 2. Spis treści Wstęp.............................................................................................................................................................. 5 Rozdział 1. Konfiguracja projektu ............................................................................................................................ 7 Kompatybilność wersji Buildera ..................................................................................................8 Podsumowanie .............................................................................................................................9 Rozdział 2. C++ w pigułce............................................................................................................................................ 11 Pliki nagłówkowe.......................................................................................................................11 Przestrzenie nazw standardowych..............................................................................................14 Klasy wejścia-wyjścia języka C++ ............................................................................................14 Obsługa plików z wykorzystaniem klasy ios.......................................................................17 Struktury w C++.........................................................................................................................18 Samodzielne tworzenie plików nagłówkowych...................................................................21 Klasy w C++ ..............................................................................................................................22 Konstruktor i destruktor .......................................................................................................27 Inne spojrzenie na klasy. Własności ....................................................................................29 Funkcje przeładowywane ...........................................................................................................31 Niejednoznaczność ..............................................................................................................33 Funkcje ogólne ...........................................................................................................................34 Przeładowywanie funkcji ogólnych .....................................................................................36 Typ wyliczeniowy ......................................................................................................................37 Dziedziczenie .............................................................................................................................38 Funkcje wewnętrzne...................................................................................................................42 Realizacja przekazywania egzemplarzy klas funkcjom .............................................................43 Tablice dynamicznie alokowane w pamięci...............................................................................45 Tablice otwarte ...........................................................................................................................48 Wskaźniki do egzemplarzy klas.................................................................................................50 Wskaźnik this .............................................................................................................................51 Obsługa wyjątków......................................................................................................................52 Podsumowanie ...........................................................................................................................56 Rozdział 3. Środowisko programisty — IDE...................................................................................................... 57 Biblioteka VCL ..........................................................................................................................59 Karta Standard .....................................................................................................................59 Karta Additional...................................................................................................................61 Karta Win32.........................................................................................................................63 Karta System ........................................................................................................................65 Karta Dialogs .......................................................................................................................66
  • 3. 4 C++Builder 6. Ćwiczenia Biblioteka CLX ..........................................................................................................................67 Karta Additional...................................................................................................................67 Karta Dialogs .......................................................................................................................68 Podsumowanie ...........................................................................................................................68 Rozdział 4. C++ w wydaniu Buildera 6 ................................................................................................................ 69 Formularz ...................................................................................................................................69 Zdarzenia ....................................................................................................................................71 Rzutowanie typów danych .........................................................................................................78 Klasa TObject.............................................................................................................................78 Wykorzystujemy własne funkcje ...............................................................................................79 Wykorzystujemy własny, nowy typ danych ..............................................................................81 Widok drzewa obiektów — Object Tree View ..........................................................................84 Komponenty TActionManager i TActionMainMenuBar ....................................................84 Typy wariantowe........................................................................................................................89 Tablice wariantowe ..............................................................................................................91 Klasy wyjątków..........................................................................................................................93 Więcej o wskaźniku this.............................................................................................................96 Podsumowanie ...........................................................................................................................98 Rozdział 5. Biblioteka CLX ......................................................................................................................................... 99 Komponenty TTimer i TLCDNumber .......................................................................................99 Podsumowanie .........................................................................................................................103 Rozdział 6. Tworzymy własne komponenty ...................................................................................................... 105 Podsumowanie .........................................................................................................................110 Rozdział 7. Aplikacje wielowątkowe ................................................................................................................... 111 Funkcja BeginThread() ............................................................................................................111 Komponent TChart...................................................................................................................114 Podsumowanie .........................................................................................................................116 Rozdział 8. C++Builder jako wydajne narzędzie obliczeniowe............................................................. 119 Obliczenia finansowe ...............................................................................................................119 Podsumowanie .........................................................................................................................126
  • 4. 2. Rozdział C++ w pigułce Ten rozdział poświęcony jest skrótowemu omówieniu podstawowych pojęć, którymi po- sługujemy się tworząc programy w C++. Zagadnienia tutaj poruszane posiadają kluczowe znaczenie dla zrozumienia idei programowania zorientowanego obiektowo w środowisku C++. U ywana terminologia oraz zamieszczone w dalszej części rozdziału przykłady (o ile nie zostały u yte elementy z biblioteki VCL) zgodne są ze standardem ANSI X3J16/ISO WG21 języka C++1. Pliki nagłówkowe W odró nieniu od programów pisanych w standardowym języku C, gdzie nie musimy zbytnio przejmować się dołączaniem do kodu źródłowego wielu plików nagłówkowych, w programach C++ nie mo na ich pominąć. Wynika to z faktu, i bardzo wiele funkcji bibliotecznych korzysta z własnych struktur oraz typów danych. W C++ ich definicje znajdują się właśnie w plikach nagłówkowych (ang. header files), które posiadają stan- dardowe rozszerzenie .h. C++ jest językiem bazującym na funkcjach, dlatego do pliku źródłowego programu musimy włączyć przy pomocy dyrektywy KPENWFG odpowiednie pliki zawierające wywoływane funkcje wraz z ich prototypami. Większość standardowych plików nagłówkowych znajduje się w katalogu instalacyjnym INCLUDE. W dalszej części rozdziału wiadomości na temat praktycznego wykorzystania zarówno standardowych, jak i samodzielnie tworzonych plików nagłówkowych znacznie rozszerzymy. Prosty przykład wykorzystania standardowych plików nagłówkowych iostream.h (zawiera definicje klas umo liwiające wykonywanie ró norodnych operacji wejścia-wyjścia na strumieniach) oraz conio.h (zawiera funkcje obsługi ekranu) zawiera poni sze ćwiczenie. 1 Musimy zauwa yć, i Borland C++Builder traktowany jako kompletne środowisko programistyczne z pewnych względów nie spełnia wymogów ISO.
  • 5. 12 C++Builder 6. Ćwiczenia Ćwiczenie 2.1. 1. Stwórzmy na dysku odrębny katalog (folder) nazywając go po prostu >. W katalogu tym przechowywane będą wszystkie pliki wykorzystywane przez aktualnie pisany program. 2. Uruchamiamy C++Buildera 6. Poleceniem menu FileNewOtherConsole Wizard otwórzmy nowy moduł. W okienku dialogowym Console Wizard w opcji Source Type wybierzmy C++, zaś w drugim panelu odznaczmy Use VCL, Use CLX, Multi Thread oraz wybierzmy Console Application, tak jak pokazuje to rysunek 2.1. Zaznaczenie tej opcji powoduje, e program będzie traktował główny formularz tak, jakby był normalnym okienkiem tekstowym. Pozostawienie aktywnej opcji Use CLX (CLX jest skrótem od angielskiego terminu, określającego pewną klasę bibliotek wspomagających proces projektowania aplikacji przenośnych pomiędzy Windows a Linux: Cluster software runing under LinuX) spowoduje automatyczne dołączenie do programu pliku nagłówkowego clx.h wspomagającego tworzenie aplikacji międzyplatformowych. Rysunek 2.1. Okno Console Wizard 3. Potwierdzając przyciskiem OK przechodzimy do okna zawierającego szkielet kodu przyszłego programu, tak jak pokazuje to rysunek 2.2. Rysunek 2.2. Kod modułu Unit1.cpp 4. Programów naszych nie będziemy uruchamiać z linii poleceń, dlatego okno edycji kodu wypełnimy tekstem pokazanym na wydruku 2.1. Następnie poleceniem FileSave As… zapiszemy nasz moduł w katalogu 01 jako 7PKVERR. Projekt modułu zapiszemy poleceniem FileSave Project As… w tym samym katalogu: 2TQLGMVADRT.
  • 6. Rozdział 2. C++ w pigułce 13 Wydruk 2.1. Kod modułu Unit01.cpp projektu Projekt_01.bpr KPENWFG KQUVTGCOJ KPENWFG EQPKQJ RTCIOC JFTUVQR KPV OCKP ] ENTUET EQWV KG FQDT[ GPFN IGVEJ TGVWTP _ 5. Po uruchomieniu programu poleceniem RunRun (F9), na ekranie w okienku udającym tryb tekstowy Windows pojawi się napis powitania. Program opuszczamy naciskając klawisz Enter. Jak widać, w skład tego programu wchodzą dwa pliki nagłówkowe: iostream.h oraz conio.h. Pierwszy z nich zdefiniowany jest w C++ i umo liwia wykonywanie szeregu operacji wejścia-wyjścia. Powodem włączenia pliku conio.h jest zastosowanie funkcji ENTUET (ang. clear screen) czyszczącej ekran tekstowy oraz funkcji IGVEJ (ang. get character) oczekującej na naciśnięcie dowolnego klawisza (wprowadzenie dowolnego znaku). U ycie dyrektywy RTCIOC JFTUVQR (ang. header stop) informuje kompilator o końcu listy plików nagłówkowych. Ka dy program pisany w C++ musi zawierać przynajmniej jedną funkcję. Główna funkcja OCKP jest tą, która zawsze musi istnieć w programie i zawsze wywoływana jest jako pierw- sza. Zestaw instrukcji właściwych danej funkcji musi być zawarty w nawiasach klamro- wych ]_, będących swojego rodzaju odpowiednikiem DGIKPGPF w Pascalu. Instrukcje zawarte w nawiasach klamrowych nazywamy blokiem instrukcji (ang. code block); jest on grupą logicznie powiązanych ze sobą elementów traktowanych jako niepodzielny fragment programu. Ka da funkcja określonego typu powinna zwracać wartość tego samego typu. W powy szym przykładzie funkcja OCKP jest typu całkowitego KPV, zatem musi zwrócić do systemu taką samą wartość. Tutaj wykonaliśmy tę operację u ywając instrukcji TGVWTP , która jest niczym innym, jak jedną z mo liwych wartości powrotnych udostępnianych w następ- stwie wywołania funkcji KPV OCKP . Je eli funkcja byłaby typu nieokreślonego, czyli XQKF (tzw. typ pusty, pusta lista parametrów), wówczas nie musielibyśmy zwracać do sys- temu adnej wartości, tak jak ilustruje to poni szy przykład: XQKF OCKP ] ENTUET EQWV KG FQDT[ GPFN IGVEJ TGVWTP _ Brak wartości zwracanej przez funkcję XQKF OCKP w powy szym przykładzie wynika z faktu, e w programach C++ nieokreślona wartość funkcji (lub pusta lista parametrów) równoznaczna jest ze słowem XQKF.
  • 7. 14 C++Builder 6. Ćwiczenia W języku C++ słowo EQWV identyfikuje ekran (ale nie formularz !), zaś wraz z operatorem pozwala wyprowadzić zarówno łańcuchy znaków, jak i zmienne wszystkich typów. Słowo GPFN (ang. end of line) odpowiada wysłaniu kombinacji znaków %4.( ustawiających kursor na początku następnego wiersza. Przestrzenie nazw standardowych Studiując niektóre programy C++ mo emy zauwa yć, i przed słowami EQWV i GPFN mo e występować słowo UVF. Informuje ono kompilator o potrzebie korzystania z tzw. wy- znacznika przestrzeni nazw. Chodzi o to, aby kompilator wiedział, e u ywamy strumieni EQWV i GPFN z biblioteki standardowej: KPENWFG KQUVTGCOJ KPV OCKP ] WUKPI UVFEQWV WUKPI UVFGPFN EQWV VGMUV GPFN _ Często te programiści, w celu uniknięcia niedogodności pisania UVF przed ka dym EQWV i GPFN, po prostu informują kompilator o potrzebie u ywania całej przestrzeni nazw standardowych, tj. e ka dy obiekt, który nie zostanie oznaczony, z zało enia będzie po- chodził z przestrzeni nazw standardowych. W tym przypadku, zamiast konstrukcji WUKPI UVFEQWV piszemy po prostu WUKPI PCOGURCEG UVF. KPENWFG KQUVTGCOJ KPV OCKP ] WUKPI PCOGURCEG UVF EQWV VGMUV GPFN _ W ksią ce tej nie będziemy jawnie rozró niać przestrzeni nazw standardowych. Klasy wejścia-wyjścia języka C++ Język C++ posługuje się kilkoma predefiniowanymi łańcuchami wejścia-wyjścia. Dwa najbardziej podstawowe z nich, związane ze standardowym wejściem-wyjściem, to EQWV oraz EKP. Z pierwszym z nich zapoznaliśmy się ju wcześniej. Słowo EKP wraz z operato- rem pozwala wprowadzać zarówno łańcuchy znaków, jak i ró nego rodzaju zmienne. Oprócz opisanych predefiniowanych łańcuchów, w C++ zdefiniowany jest jeszcze szereg tzw. klas strumieni wejścia-wyjścia. Trzy podstawowe klasy wejścia-wyjścia to:
  • 8. Rozdział 2. C++ w pigułce 15 QHUVTGCO (ang. output file stream) — wyprowadzanie danych, KHUVTGCO (ang. input file stream) — wprowadzanie danych, HUVTGCO (ang. file stream) — wprowadzanie i wyprowadzanie danych. Dwa proste ćwiczenia pozwolą nam zapoznać się z właściwościami wymienionych klas. Ćwiczenie 2.2. Zaprojektujemy program, którego jedynym zadaniem będzie odczytanie swojego własnego tekstu źródłowego zawartego w pliku .cpp i wyświetlenie go na ekranie. Kod tego pro- gramu, korzystającego z uniwersalnej klasy HUVTGCO, pokazany jest na wydruku 2.2. Wydruk 2.2. Moduł Unit02.cpp projektu Projekt_02.bpr KPENWFG KQUVTGCOJ KPENWFG HUVTGCOJ KPENWFG EQPKQJ RTCIOC JFTUVQR KPV OCKP ] EJCT DWHQT=? HUVTGCO +P(KNG ENTUET +P(KNGQRGP 7PKVERR YJKNG +P(KNGGQH ] +P(KNGIGVNKPG DWHQT UKGQH DWHQT EQWV DWHQT GPFN _ +P(KNGENQUG IGVEJ TGVWTP _ Wykorzystanie omawianych na początku niniejszego podrozdziału klas wejścia-wyjścia wymaga włączenia do programu pliku nagłówkowego fstream.h, tak jak wykonaliśmy to w linii 2. programu. Dane z pliku będziemy wczytywać znak po znaku, zatem wymagane jest zadeklarowa- nie w linii 7. programu bufora danych typu znakowego EJCT o odpowiednim rozmiarze. Chocia budowę klas i ró ne aspekty ich wykorzystywania omówimy dokładniej w dalszej części rozdziału, jednak ju w tym miejscu zaczniemy posługiwać się odpo- wiednią terminologią. Omawiając deklarację z linii 8. w sposób tradycyjny, powiedzie- libyśmy, i została tam zadeklarowana zmienna +P(KNG typu HUVTGCO. Jednak w odnie- sieniu do klas wygodniej jest posługiwać się innym sformułowaniem — powiemy, e w linii 8. programu zadeklarowaliśmy egzemplarz +P(KNG klasy HUVTGCO (bardzo często u ywa się te sformułowania, e został utworzony strumień wejściowy +P(KNG). Jak zapewne wiesz, ka dy plik, którego zawartość chcemy w odpowiedni sposób wy- świetlić, musi być najpierw otwarty do czytania. Czynność tę wykonujemy w linii 9. poprzez odwołanie się do egzemplarza (obiektu) klasy HUVTGCO z jawnym wskazaniem
  • 9. 16 C++Builder 6. Ćwiczenia funkcji, jakiej ma u ywać do otwarcia pliku. W terminologii stosowanej w programowaniu zorientowanym obiektowo powiemy, i strumień wejściowy +P(KNG połączyliśmy z pli- kiem dzięki wywołaniu funkcji składowej klasy (metody) QRGP , której argumentem jest nazwa pliku umieszczona w podwójnych apostrofach. W przypadku, gdy czytany plik nie znajduje się w aktualnym katalogu, nale y podać pełną ście kę dostępu według następującego przepisu: +P(KNGQRGP EEYDKNFAMQF[7PKVERR Proces czytania i wyświetlania na ekranie zawartości pliku wykonywany jest w liniach 11. – 14. przy pomocy instrukcji iteracyjnej YJKNG, która będzie wykonywana do czasu napotkania znacznika końca pliku. Osiągnięcie końca pliku wykrywamy za pomocą funkcji składowej GQH (ang. end of file). W linii 12. przy pomocy dwuparametrowej funkcji składowej IGVNKPG wczytujemy za- wartość pliku do bufora. Pierwszym parametrem tej funkcji jest zmienna DWHQT identyfi- kująca bufor danych wejściowych. Drugim parametrem jest jednoargumentowy operator czasu kompilacji UKGQH udostępniający długość zmiennej DWHQT. Operator ten wykorzy- stujemy w przypadku, gdy wymagamy, aby kod źródłowy programu był w du ej mierze przenośny, tzn. by mo na było wykorzystywać go na ró nego rodzaju komputerach. Bar- dzo często warunek przenośności kodu wymaga, aby ustalić rzeczywistą długość da- nych, np. typu EJCT. W linii 15. wywołujemy funkcję składową ENQUG zamykającą otwarty uprzednio plik. Ćwiczenie 2.3. Obecne ćwiczenie ilustruje sposób posługiwania się klasami QHUVTGCO oraz KHUVTGCO. Poprzedni program został zmodyfikowany w taki sposób, aby po utworzeniu w aktual- nym katalogu nowego pliku mo na było zapisać w nim odpowiednie dane, którymi w tym przypadku są wartości funkcji UKP (sinus), której prototyp znajduje się w pliku nagłów- kowym math.h. Wydruk 2.3. Moduł Unit03.cpp projektu Projekt_03.bpr KPENWFG KQUVTGCOJ KPENWFG HUVTGCOJ KPENWFG OCVJJ KPENWFG EQPKQJ RTCIOC JFTUVQR KPV OCKP ] EJCT DWHQT=? ENTUET VYQTGPKG PQYGIQ RNKMW K CRKU FCP[EJ PC F[UM QHUVTGCO 1WV(KNG PQY[FCV KH 1WV(KNG TGVWTP HQT KPV K K K 1WV(KNG UKP K GPFN 1WV(KNGENQUG
  • 10. Rozdział 2. C++ w pigułce 17 QFE[V FCP[EJ KHUVTGCO +P(KNG PQY[FCV YJKNG +P(KNGGQH ] +P(KNGIGVNKPG DWHQT UKGQH DWHQT EQWV DWHQT GPFN _ +P(KNGENQUG IGVEJ TGVWTP _ Analizując powy sze zapisy łatwo zauwa ymy, i zaraz po utworzeniu nowego pliku, przy pomocy instrukcji warunkowej KH sprawdzamy, czy czynność ta została wykonana pomyślnie. W przypadku niemo ności stworzenia na dysku pliku o podanej nazwie, przy pomocy instrukcji TGVWTP wywołujemy wartość powrotną funkcji OCKP , co jest równoznaczne z opuszczeniem programu. W omawianym programie nie została u yta funkcja QRGP . Funkcji tej nie u ywa się zbyt często korzystając z klas strumieni, z tego względu, i klasy HUVTGO, KHUVTGO oraz QHUVTGO posiadają odpowiednie konstruktory (inne funkcje składowe), które otwierają pliki automatycznie. Obsługa plików z wykorzystaniem klasy ios Jak zapewne pamiętasz, istnieją dwa podstawowe rodzaje plików, którymi w praktyce po- sługujemy się najczęściej. Są to pliki tekstowe oraz binarne. Pliki tekstowe, stanowiące zbiór znaków ASCII (lub Unicode), przechowują zawarte w nich informacje w kolejnych wierszach, z których ka dy zakończony jest parą znaków %4 .(. Pliki binarne zawierające kodowane dane ró nią się od tekstowych tym, i informacje w nich zawarte nie są prze- znaczone do bezpośredniego oglądania — są zrozumiałe jedynie dla określonych progra- mów. Bardzo wygodny dostęp do ró nego rodzaju plików dają nam elementy klasy KQU. Wspomniano wcześniej, e jednym ze sposobów połączenia uprzednio utworzonego stru- mienia z plikiem jest wywołanie funkcji: XQKF QRGP EQPUV EJCT
  • 11. U KQUADCUGQRGPOQFG KQUADCUGQWV ^ KQUADCUGKP NQPI RTQVGEVKQP gdzie U oznacza nazwę pliku, która mo e zawierać pełną ście kę dostępu. Tryb otwarcia pliku określa parametr QRGPOQFG, który musi być przedstawiony w postaci jednej lub większej liczby określonych wartości, połączonych przy pomocy operatora binarnej sumy logicznej ^. W tabeli 2.1 zebrano dostępne wartości, jakie mo e przyjmować parametr QRGPOQFG. Natomiast parametr RTQVGEVKQP opcjonalnie określa otwarcie zwykłego pliku. Je eli zechcemy, aby plik został otworzony np. w trybie do dopisywania, wystarczy po- słu yć się bardzo prostą konstrukcją: QHUVTGCO 1WV(KNG PQY[FCV KQUCRR A dopisywania w trybie binarnym: QHUVTGCO 1WV(KNG PQY[FCV KQUCRR ^ KQUDKPCT[
  • 12. 18 C++Builder 6. Ćwiczenia Tabela 2.1. Dopuszczalne tryby otwarcia pliku Wartości openmode Opis KQUCRR Otwarcie pliku w trybie do dopisywania (dołączenie wprowadzanych danych na końcu pliku). KQUCVG Ustawienie wskaźnika pliku na jego końcu. KQUKP Otwarcie pliku w tzw. trybie wejściowym (w trybie do czytania). Wartość domyślna dla strumienia KHUVTGCO. KQUQWV Otwarcie pliku w tzw. trybie wyjściowym (w trybie do zapisywania). Wartość domyślna dla strumienia QHUVTGCO. KQUDKPCT[ Otwarcie pliku binarnego. KQUVTWPE Po otwarciu zawartość pliku zostanie usunięta. Ćwiczenie 2.4. Korzystając z tabeli 2.1 zmodyfikuj projekt Projekt_03.bpr (wydruk 2.3) w ten sposób, aby sprawdzić działanie pozostałych metod otwarcia pliku. Struktury w C++ Struktury, tworzące zbiór zmiennych zło onych z jednej lub z logicznie powiązanych kilku danych ró nych typów, zgrupowanych pod jedną nazwą, są bardzo wygodnym typem danych, często definiowanym przez programistów C++. Na potrzeby obecnych ćwiczeń przedstawimy dwa bardzo często stosowane sposoby deklaracji oraz u ywania struktur. Słowo kluczowe UVTWEV (struktura) ułatwia logiczne pogrupowanie danych ró nych typów. Po słowie UVTWEV w nawiasach klamrowych deklarujemy elementy składowe struktury wraz z ich typami bazowymi. Ćwiczenie 2.5. Zbudujemy naprawdę prostą bazę danych, w której przechowywać będziemy pewne in- formacje o wybranych studentach, tak jak pokazano to na wydruku 2.4. Wydruk 2.4. Moduł Unit04.cpp projektu Projekt_04.bpr ilustrującego prosty przykład wykorzystania informacji zawartej w pewnej strukturze KPENWFG KQUVTGCOJ KPENWFG EQPKQJ KPENWFG UVFNKDJ RTCIOC JFTUVQR UVTWEV 5VWFGPV] EJCT +OKG=? EJCT 0CYKUMQ=? HNQCV 'ICOKP/CVGOCV[MC HNQCV 'ICOKP(K[MC HNQCV 'ICOKP+PHQTOCV[MC
  • 13. Rozdział 2. C++ w pigułce 19 EJCT ,CMK5VWFGPV=? _ XQKF 5VWFGPV+PHQ KPV 5VWFGPV +PHQ KPV OCKP ] 5VWFGPV CPG=? KPV KPFGZ EJCT DWHQT/=?DWHQT(=?DWHQT+=? ENTUET FQ ] EQWV +OKG EKPIGVNKPG CPG=KPFGZ?+OKG UKGQH CPG=KPFGZ?+OKG EQWV 0CYKUMQ EKPIGVNKPG CPG=KPFGZ?0CYKUMQ UKGQH CPG=KPFGZ?0CYKUMQ EQWV 'ICOKP /CVGOCV[MC EKPIGVNKPG DWHQT/ UKGQH DWHQT/ CPG=KPFGZ?'ICOKP/CVGOCV[MC CVQH DWHQT/ CVQH EQWV 'ICOKP (K[MC EKPIGVNKPG DWHQT( UKGQH DWHQT( CPG=KPFGZ?'ICOKP(K[MC CVQH DWHQT( EQWV 'ICOKP +PHQTOCV[MC EKPIGVNKPG DWHQT+ UKGQH DWHQT+ CPG=KPFGZ?'ICOKP+PHQTOCV[MC CVQH DWHQT+ EQWV 1RKPKC EKPIGVNKPG CPG=KPFGZ?,CMK5VWFGPV UKGQH CPG=KPFGZ?,CMK5VWFGPV EQWV GPFN KPFGZ _ YJKNG KPFGZ HQT KPV K K K 5VWFGPV+PHQ K CPG=K? IGVEJ TGVWTP _ XQKF 5VWFGPV+PHQ KPV PWOGT 5VWFGPV +PHQ ] EQWV 1UQDC TGMQTF PT PWOGT GPFN EQWV +OKú K 0CYKUMQ +PHQ+OKG EQWV +PHQ0CYKUMQ GPFN EQWV 'ICOKP /CVGOCV[MC +PHQ'ICOKP/CVGOCV[MC GPFN EQWV 'ICOKP (K[MC +PHQ'ICOKP(K[MC GPFN EQWV 'ICOKP +PHQTOCV[MC +PHQ'ICOKP+PHQTOCV[MC GPFN EQWV 1RKPKC +PHQ,CMK5VWFGPV GPFN _
  • 14. 20 C++Builder 6. Ćwiczenia W programie głównym w liniach 5. – 12. definiujemy strukturę 5VWFGPV, w której polach zapisywać będziemy interesujące nas informacje, czyli imię i nazwisko danej osoby, oceny z egzaminów z wybranych przedmiotów i na koniec naszą opinię o studencie. Poniewa chcemy mieć mo liwość przechowywania w polach struktury informacji o więk- szej liczbie osób, dlatego w linii 16. deklarujemy tablicę CPG typu strukturalnego 5VWFGPV. Informacje przechowywane w polach struktury będą indeksowane, musimy zatem za- deklarować w linii 17. zmienną KPFGZ typu całkowitego. Oceny z poszczególnych egzaminów deklarowane są w strukturze 5VWFGPV jako prosty typ zmiennopozycyjny HNQCV. W trakcie działania programu oceny te wpisywać bę- dziemy z klawiatury w postaci ciągu znaków, które w dalszym etapie powinny zostać przekonwertowane na konkretne liczby. Z tego powodu łańcuchy znaków reprezentują- cych poszczególne oceny będą przechowywane w odpowiednich buforach deklarowa- nych w linii 18. programu. Proces wypełniania poszczególnych pól tablicy struktur CPG odbywa się w liniach 20. – 38. programu w pętli FQYJKNG. I tak, w pierwszej kolejności za pomocą funkcji składo- wej IGVNKPG strumienia wejściowego EKP wypełniamy pola +OKG oraz 0CYKUMQ tablicy struktur CPG (linie 22. – 24.). Elementy tablicy struktur (osoby) są indeksowane po- cząwszy od wartości . W linii 26. wczytujemy do bufora DWHQT/ ciąg znaków reprezentujących ocenę z wybra- nego przedmiotu. W linii 27. ciąg znaków znajdujący się w buforze zostanie zamienio- ny na liczbę typu zmiennopozycyjnego za pomocą zdefiniowanej w pliku nagłówko- wym stdlib.h funkcji CVQH . W tej samej linii programu liczba ta zostanie wpisana do pola 'ICOKP/CVGOCV[MC tablicy struktur CPG z odpowiednim indeksem określającym konkretną osobę. W podobny sposób wypełniamy pozostałe pola tablicy struktur CPG do momentu, kiedy zmienna KPFGZ nie przekroczy wartości określającej liczbę „zapamięta- nych” osób. W dalszym etapie rozwoju naszego programu zajdzie prawdopodobnie potrzeba po- nownego wyświetlenia (lub wyszukania i wyświetlenia) informacji o wybranych oso- bach (lub konkretnej osobie). Musimy zatem zaprojektować prostą funkcję rozwiązują- cą ten problem. W C++ istnieje konieczność deklarowania prototypów samodzielnie definiowanych funkcji. Prototyp naszej funkcji 5VWFGPV+PHQ typu XQKF (funkcja nie zwraca adnej wartości) umieszczony jest w linii 13. programu. Funkcja posiada dwa parametry: pierwszy typu całkowitego KPV, określający numer osoby, drugi +PHQ typu strukturalnego 5VWFGPV, umo liwiający odwoływanie się do konkretnych pól struktury (informacji zawartych w strukturze). Zapis funkcji 5VWFGPV+PHQ znajduje się w liniach 44. – 53. naszego programu. Łatwo zauwa ymy, i odpowiednie dane pobierane są z określonych pól struktury poprzez strumień wyjściowy EQWV. Proces wyświetlania danych na ekranie odbywa się w liniach 39. – 40., gdzie zmienna ste- rująca K w pętli HQT przebiega ju tylko indeksy tablicy struktur CPG. Na rysunku 2.3 pokazano omawiany program w trakcie działania.
  • 15. Rozdział 2. C++ w pigułce 21 Rysunek 2.3. Projekt Projekt_04.bpr po uruchomieniu Samodzielne tworzenie plików nagłówkowych Wspominaliśmy wcześniej, i w C++ bardzo wiele funkcji bibliotecznych korzysta z wła- snych struktur oraz typów danych, których definicje znajdują się w plikach nagłówkowych. Korzystając z faktu, i stworzyliśmy przed chwilą własny strukturalny typ danych, zmo- dyfikujemy Projekt_04.bpr w ten sposób, aby posługiwał się plikiem nagłówkowym zawie- rającym definicję struktury 5VWFGPV. Ćwiczenie 2.6. 1. Poleceniem menu FileNewOtherHeader File uaktywniamy okno edycji ułatwiające tworzenie i zapisywanie na dysku własnych, nowo tworzonych plików nagłówkowych. 2. Kod pliku zaczyna się od dyrektywy kompilacji warunkowej KHPFGH (ang. if not defined — jeśli nie zdefiniowano). Za dyrektywą następuje pisana du ymi literami nazwa makra z reguły rozpoczynająca się od znaku podkreślenia. 3. Następnie, przy pomocy dyrektywy FGHKPG definiujemy nazwę makra w ten sposób, aby zaczynała się od znaku podkreślenia. Nazwa makra powinna odpowiadać nazwie, którą później nadamy plikowi nagłówkowemu. 4. Po zdefiniowaniu makra, nale y zdefiniować własny typ strukturalny. 5. Definicja makra kończy się dyrektywą kompilacji warunkowej GPFKH. KHPFGH A567'06A* CNG PKG KHFGH FGHKPG A567'06* UVTWEV 5VWFGPV] EJCT +OKG=? EJCT 0CYKUMQ=? HNQCV 'ICOKP/CVGOCV[MC HNQCV 'ICOKP(K[MC HNQCV 'ICOKP+PHQTOCV[MC EJCT ,CMK5VWFGPV=? _ GPFKH
  • 16. 22 C++Builder 6. Ćwiczenia 6. Tak określony plik nagłówkowy zapiszemy w aktualnym katalogu pod nazwą UVWFGPVJ. Bardzo często (nawet przez nieuwagę) osoby rozpoczynające naukę C++ popełniają pewien błąd. Mianowicie zamiast dyrektywy KHPFGH u ywają bardzo podobnej w zapisie KHFGH (ang. if defined — jeśli zdefiniowano). Ró nica pomiędzy tymi dyrektywami jest dosyć wyraźna. Je eli za pomocą dyrektywy FGHKPG została wcześniej zdefiniowana pewna makrodefinicja, wówczas sekwencja instrukcji występująca pomiędzy dyrektywami KHFGH oraz GPFKH będzie zawsze kompilowana. Sekwencja instrukcji występująca pomiędzy dyrektywami KHPFGH oraz GPFKH będzie kompilowana jedynie wówczas, gdy dana makrodefinicja nie została wcześniej zdefiniowana. 7. Tak przygotowany plik nagłówkowy zawierający definicję struktury 5VWFGPV bez problemu wykorzystamy w naszym programie. W tym celu wystarczy dołączyć go do kodu zaraz po dyrektywie RTCIOC JFTUVQR: RTCIOC JFTUVQR KPENWFG UVWFGPVJ XQKF 5VWFGPV+PHQ KPV 5VWFGPV +PHQ Zmodyfikowany Projekt_04.bpr mo emy ju samodzielnie przetestować. Klasy w C++ Klasa jest jednym z podstawowych pojęć obiektowego języka C++. Przy pomocy słowa kluczowego ENCUU definiujemy nowy typ danych, będący w istocie połączeniem danych i instrukcji, które wykonują na nich działania. Umo liwia on tworzenie nowych (lub wyko- rzystanie istniejących) obiektów będących reprezentantami klasy. Konstrukcja klasy umo li- wia deklarowanie elementów prywatnych (ang. private), publicznych (ang. public) oraz chronionych (ang. protected). Domyślnie, w standardowym języku C++ wszystkie ele- menty klasy traktowane są jako prywatne, co oznacza, e dostęp do nich jest ściśle kontro- lowany i adna funkcja nie nale ąca do klasy nie mo e z nich korzystać. Je eli w definicji klasy pojawią się elementy publiczne, oznacza to, e mogą one uzyskiwać dostęp do innych części programu. Chronione elementy klasy dostępne są jedynie w danej klasie lub w kla- sach potomnych. Ogólną postać definicji klasy mo na przedstawić w sposób następujący: ENCUU 0CYC-NCU[ ] RTKXCVG RT[YCVPG FCPG K HWPMELG RWDNKE RWDNKEPG FCPG K HWPMELG RTQVGEVGF EJTQPKQPG FCPG K HWPMELG _ 'IGORNCTG-NCU[ NKUVC GIGORNCT[ MNCU[
  • 17. Rozdział 2. C++ w pigułce 23 Definicja klasy jest zawsze źródłem definicji jej obiektów. Jeszcze kilkanaście lat temu przed pojawieniem się wizualnych środowisk programistycznych słowo obiekt (ang. object) było jednoznacznie uto samiane z klasą2. Obecnie sytuacja nieco się skompliko- wała, gdy słowo obiekt otrzymało o wiele szersze znaczenie. Z tego względu wygodniej jest posługiwać się szeroko stosowanym w anglojęzycznej literaturze sformułowaniem egzemplarz klasy (ang. class instance). Otó , po zdefiniowaniu klasy tworzymy obiekt jej typu o nazwie takiej samej, jak nazwa klasy występująca po słowie ENCUU. Jednak klasy tworzymy po to, by stały się specyfikatorami typów danych. Je eli w instrukcji definicji klasy po zamykającym nawiasie klamrowym podamy pewną nazwę, utworzymy tym samym określony egzemplarz klasy, który od tej chwili traktowany jest jako nowy, pełnoprawny typ danych. Oczywiście jedna klasa mo e być źródłem definicji wielu jej egzemplarzy. Innym sposobem utworzenia egzemplarza danej klasy będzie następująca konstrukcja: ENCUU 0CYC-NCU[ ] RTKXCVG RT[YCVPG FCPG K HWPMELG RWDNKE RWDNKEPG FCPG K HWPMELG RTQVGEVGF EJTQPKQPG FCPG K HWPMELG _ KPV OCKP 'IGORNCT-NCU[ 0CYC-NCU[ Ćwiczenie 2.7. Jako przykład stworzymy bardzo prostą w swojej budowie klasę 5VWFGPV, przy pomocy której będziemy mogli odczytać wybrane informacje o pewnej osobie. 1. Deklaracja klasy 5VWFGPV składającej się z części publicznej i prywatnej mo e wyglądać następująco: ENCUU 5VWFGPV ] RWDNKE XQKF ,CMK5VWFGPV EJCT
  • 18. XQKF +PKELCNKCELC XQKF (KPCNKCELC RTKXCVG EJCT
  • 19. 0CYKUMQ _ W sekcji publicznej (rozpoczynającej się od słowa kluczowego RWDNKE) deklaracji klasy 5VWFGPV umieściliśmy prototypy trzech funkcji składowych klasy. W sekcji prywatnej (rozpoczynającej się od słowa kluczowego RTKXCVG) umieściliśmy deklarację 2 Jako ciekawostkę podajmy, i w latach 70. XX wieku słowo obiekt uto samiano z pewnym wydzielonym obszarem pamięci w du ych maszynach cyfrowych oraz innych maszynach zwanych mini- i mikrokomputerami. W takim znaczeniu słowa obiekt u ywali Brian Kernighan i Dennis Ritchie — twórcy języka C.
  • 20. 24 C++Builder 6. Ćwiczenia jednej zmiennej (dokładniej — wskaźnika) składowej klasy. Mimo e istnieje mo liwość deklarowania zmiennych publicznych w klasie, to jednak zalecane jest, aby ich deklaracje były umieszczane w sekcji prywatnej, zaś dostęp do nich był mo liwy poprzez funkcje z sekcji publicznej. Jak ju się zapewne domyślasz, dostęp do wskaźnika 0CYKUMQ z sekcji prywatnej będzie mo liwy właśnie poprzez funkcję ,CMK5VWFGPV , której jedynym parametrem jest wskaźnik. Tego typu technika programowania nosi nazwę enkapsulacji danych, co oznacza, e dostęp do prywatnych danych jest zawsze ściśle kontrolowany. 2. Jak się zapewne domyślasz, rolą bezparametrowej funkcji +PKELCNKCELC będzie zainicjowanie danych. Poniewa omawiana funkcja jest częścią klasy 5VWFGPV, to przy jej zapisie w programie musimy poinformować kompilator, i właśnie do niej nale y. Operator rozró niania zakresu (ang. scope resolution operator) słu y temu celowi. XQKF 5VWFGPV+PKELCNKCELC ] 0CYKUMQ PGY EJCT=? EQWV 2T[FKGNQPQ RCOKúè EQWV GPFN 0CEK PKL 'PVGT GPFN IGVEJCT TGVWTP _ Jedyną rolą funkcji +PKELCNKCELC jest dynamiczne przydzielenie pamięci do wskaźnika 0CYKUMQ przy pomocy operatora PGY. Tekst wyświetlany jest jedynie w celach poglądowych. 3. Funkcja (KPCNKCELC zajmuje się zwolnieniem przy pomocy operatora FGNGVG uprzednio przydzielonej pamięci. XQKF 5VWFGPV(KPCNKCELC ] FGNGVG=? 0CYKUMQ EQWV YQNPKQPQ RCOKúè EQWV GPFN 0CEK PKL 'PVGT GPFN TGVWTP _ 4. W funkcji ,CMK5VWFGPV dokonujemy porównania dwóch ciągów znaków. Przy pomocy funkcji UVTEOR z modułu UVTKPIJ porównujemy dwa łańcuchy znaków, czyli łańcuch wskazywany przez 0CYKUMQ oraz drugi, odpowiadający ju konkretnemu nazwisku danej osoby. Je eli oba łańcuchy są identyczne, funkcja UVTEOR zwraca wartość , zaś następnie przy pomocy strumienia wyjściowego EQWV wyświetlany jest odpowiedni komunikat. XQKF 5VWFGPV,CMK5VWFGPV EJCT
  • 21. U ] 0CYKUMQ U KH UVTEOR 0CYKUMQ 9CEMQYUMK UVTER[ 0CYKUMQ DCTFQ FQDT[ UVWFGPV KH UVTEOR 0CYKUMQ ,CPMQYUMK UVTER[ 0CYKUMQ MKGRUMK UVWFGPV EQWV 0CYKUMQ GPFN GPFN TGVWTP _
  • 22. Rozdział 2. C++ w pigułce 25 5. W głównej funkcji OCKP wywołamy opisane wcześniej elementy klasy 5VWFGPV. KPV OCKP ] EJCT
  • 23. -VQT[5VWFGPV -VQT[5VWFGPV PGY EJCT=? 5VWFGPV +PHQ5VWFGPV ENTUET EQWV 2QFCL PCYKUMQ IGVU -VQT[5VWFGPV +PHQ5VWFGPV+PKELCNKCELC +PHQ5VWFGPV,CMK5VWFGPV -VQT[5VWFGPV +PHQ5VWFGPV(KPCNKCELC IGVEJ FGNGVG=? -VQT[5VWFGPV TGVWTP _ I tak, w linii 3. deklarujemy wskaźnik -VQT[5VWFGPV przechowujący wpisywane z klawiatury nazwisko (dokładniej — wskazujący na pierwszą literę nazwiska), zaś w linii 4. przydzielamy mu przy pomocy operatora PGY odpowiedni obszar pamięci. W linii 5. deklarujemy egzemplarz +PHQ5VWFGPV klasy 5VWFGPV. W liniach 6. – 8. wczytujemy nazwisko studenta. Poniewa u ywamy wskaźnika, wygodniej jest w tym celu wykorzystać funkcję IGVU , której prototyp znajduje się w pliku stdio.h. W liniach 10. i 11. w odpowiedniej kolejności wywołujemy funkcje składowe egzemplarza +PHQ5VWFGPV klasy 5VWFGPV. Aby wywołać funkcję składową egzemplarza klasy z fragmentu programu nie nale ącego do klasy (w naszym przypadku z głównej funkcji OCKP ), nale y w kolejności podać: nazwę egzemplarza klasy, operator w postaci kropki, zaś po nim nazwę właściwej funkcji. W linii 13. zwalniamy pamięć przydzieloną wskaźnikowi -VQT[5VWFGPV. Kompletny kod modułu Unit05.cpp projektu Projekt_05.bpr korzystającego z omawianej klasy przedstawiono na wydruku 2.5, zaś na rysunku 2.4 pokazano efekt naszej pracy. Wydruk 2.5. Kod modułu Unit05.cpp KPENWFG KQUVTGCOJ KPENWFG UVTKPIJ KPENWFG EQPKQJ KPENWFG UVFKQJ RTCIOC JFTUVQR ENCUU 5VWFGPV ] RTKXCVG EJCT
  • 24. 0CYKUMQ RWDNKE XQKF ,CMK5VWFGPV EJCT
  • 25. XQKF +PKELCNKCELC XQKF (KPCNKCELC _ +PHQ5VWFGPV XQKF 5VWFGPV+PKELCNKCELC ] 0CYKUMQ PGY EJCT=? EQWV 2T[FKGNQPQ RCOKúè EQWV GPFN 0CEK PKL 'PVGT GPFN
  • 26. 26 C++Builder 6. Ćwiczenia IGVEJCT TGVWTP _ XQKF 5VWFGPV(KPCNKCELC ] FGNGVG=? 0CYKUMQ EQWV YQNPKQPQ RCOKúè EQWV GPFN 0CEK PKL 'PVGT GPFN TGVWTP _ XQKF 5VWFGPV,CMK5VWFGPV EJCT
  • 27. U ] 0CYKUMQ U KH UVTEOR 0CYKUMQ 9CEMQYUMK UVTER[ 0CYKUMQ DCTFQ FQDT[ UVWFGPV KH UVTEOR 0CYKUMQ ,CPMQYUMK UVTER[ 0CYKUMQ MKGRUMK UVWFGPV EQWV 0CYKUMQ GPFN GPFN TGVWTP _ KPV OCKP ] EJCT
  • 28. -VQT[5VWFGPV -VQT[5VWFGPV PGY EJCT=? 5VWFGPV +PHQ5VWFGPV ENTUET EQWV 2QFCL PCYKUMQ IGVU -VQT[5VWFGPV +PHQ5VWFGPV+PKELCNKCELC +PHQ5VWFGPV,CMK5VWFGPV -VQT[5VWFGPV +PHQ5VWFGPV(KPCNKCELC IGVEJ FGNGVG=? -VQT[5VWFGPV TGVWTP _ Rysunek 2.4. Projekt Projekt_05.bpr w trakcie działania
  • 29. Rozdział 2. C++ w pigułce 27 Konstruktor i destruktor Przedstawiony na przykładzie projektu Projekt_05.bpr sposób inicjowania i finalizowania działania ró nych obiektów (w tym egzemplarzy klas) jest obecnie rzadko wykorzystywany w praktyce (poza zupełnie szczególnymi przypadkami, w których mamy jakieś konkretne wymagania odnośnie działania programu). Poniewa konieczność inicjalizowania (i ew. finalizowania) np. egzemplarzy klas w C++ występuje bardzo często, dlatego w praktyce wykorzystujemy automatyczną ich inicjalizację (i ew. finalizację). Tego rodzaju automaty- zacja mo liwa jest dzięki wykorzystaniu specjalnych funkcji składowych klasy zwanych konstruktorami. Konstruktor i destruktor zawsze posiadają taką samą nazwę jak klasa, do której nale ą. Ró nica w ich zapisie polega na tym, e nazwa destruktora poprzedzona jest znakiem `. Ćwiczenie 2.8. Zmodyfikujemy poprzedni program w taki sposób, aby klasa 5VWFGPV posiadała swój kon- struktor i destruktor. 1. Po wprowadzeniu konstruktora i destruktora do klasy 5VWFGPV, jej definicja przybierze następującą postać: ENCUU 5VWFGPV ] RWDNKE XQKF ,CMK5VWFGPV EJCT
  • 30. 5VWFGPV MQPUVTWMVQT `5VWFGPV FGUVTWMVQT RTKXCVG EJCT
  • 31. 0CYKUMQ _ Natychmiast zauwa ymy, i w C++ nie określa się typów powrotnych konstruktorów i destruktorów, gdy z zało enia nie mogą zwracać adnych wartości. 2. Zrozumienie idei u ywania konstruktorów i destruktorów ułatwi nam prześledzenie poni szego wydruku. Wydruk 2.6. Kod modułu Unit06.cpp projektu Projekt_06.bpr wykorzystującego funkcje składowe w postaci konstruktora i destruktora klasy KPENWFG KQUVTGCOJ KPENWFG UVTKPIJ KPENWFG EQPKQJ KPENWFG UVFKQJ RTCIOC JFTUVQR ENCUU 5VWFGPV ] RWDNKE XQKF ,CMK5VWFGPV EJCT
  • 32. 5VWFGPV MQPUVTWMVQT `5VWFGPV FGUVTWMVQT RTKXCVG EJCT
  • 33. 0CYKUMQ _
  • 34. 28 C++Builder 6. Ćwiczenia MQPUVTWMVQT MNCU[ 5VWFGPV 5VWFGPV5VWFGPV ] 0CYKUMQ PGY EJCT=? EQWV -QPUVTWMVQT MNCU[ QUVC CKPKELQYCP[ EQWV GPFN 0CEK PKL 'PVGT GPFN IGVEJCT _ XQKF 5VWFGPV,CMK5VWFGPV EJCT
  • 35. U ] 0CYKUMQ U KH UVTEOR 0CYKUMQ 9CEMQYUMK UVTER[ 0CYKUMQ DCTFQ FQDT[ UVWFGPV KH UVTEOR 0CYKUMQ ,CPMQYUMK UVTER[ 0CYKUMQ MKGRUMK UVWFGPV EQWV 0CYKUMQ GPFN EQWV GPFN 0CEK PKL MNCYKU GPFN TGVWTP _ FGUVTWMVQT MNCU[ 5VWFGPV 5VWFGPV`5VWFGPV ] FGNGVG=? 0CYKUMQ EQWV -QPUVTWMVQT QUVC PKUEQP[ 2QYVÎTPKG PCEK PKL MNCYKU GPFN IGVEJ _ KPV OCKP ] EJCT
  • 36. -VQT[5VWFGPV -VQT[5VWFGPV PGY EJCT=? 5VWFGPV +PHQ5VWFGPV ENTUET EQWV 2QFCL PCYKUMQ IGVU -VQT[5VWFGPV +PHQ5VWFGPV,CMK5VWFGPV -VQT[5VWFGPV IGVEJ FGNGVG=? -VQT[5VWFGPV TGVWTP _ Uruchamiając program bez trudu przekonamy się, i konstruktor 5VWFGPV jest automa- tycznie uruchamiany podczas tworzenia egzemplarza klasy, czyli w momencie wykonywania instrukcji deklarującej egzemplarz klasy. Jest to jedna z cech odró niających język C++ od zwykłego C. W C++ deklaracje zmiennych wykonywane są w trakcie działania programu. Ze względu na to, e ka dy egzemplarz klasy jest tworzony w trakcie wykonywania in- strukcji jego deklaracji, musi on być niszczony automatycznie w trakcie opuszczania bloku programu, w którym powy sza deklaracja się znajduje. Testując projekt Projekt_06.bpr bez trudu przekonamy się, i mimo e destruktor `5VWFGPV nie został jawnie wywołany, to jednak kod jego zostanie wykonany, zwalniając tym samym pamięć przydzieloną uprzed- nio wskaźnikowi 0CYKUMQ przez konstruktor 5VWFGPV .
  • 37. Rozdział 2. C++ w pigułce 29 Ćwiczenie 2.9. Samodzielnie przetestuj projekty Projekt_05.bpr oraz Projekt_06.bpr pod kątem okre- ślenia ró nic w działaniu zwykłych funkcji składowych +PKELCNKCELC i (KPCNKCELC oraz konstruktora 5VWFGPV i destruktora `5VWFGPV . Ćwiczenie 2.10. Często, w celu uczynienia programu bardziej przejrzystym, definicje klas umieszczamy w oddzielnym pliku nagłówkowym. Postaraj się samodzielnie stworzyć taki plik i włączyć go do programu. Inne spojrzenie na klasy. Własności C++Builder, jako kompletne środowisko programowania, wprowadza bardziej ogólne pojęcie klasy. Otó w Builderze definicję klasy mo na znacznie wzbogacić, tzn. w skład tej definicji oprócz sekcji prywatnej i publicznej mo e wchodzić równie sekcja publi- kowana (ang. published) rozpoczynająca się od słowa kluczowego AARWDNKUJGF. W tej sekcji umieszcza się z reguły deklaracje funkcji, czyli deklaracje metod związane z kom- ponentami pochodzącymi z biblioteki VCL. Dodatkowo klasa mo e zawierać te definicje własności rozpoczynające się od słowa AARTQRGTV[. Warto w tym miejscu zauwa yć, i definicje w klasie związane z biblioteką VCL będą rozpoczynać się od pewnych słów kluczowych, poprzedzonych podwójnym znakiem podkreślenia. Chocia do klas związanych z biblioteką komponentów wizualnych powrócimy jeszcze w dalszej części ksią ki, to jednak w tym miejscu poka emy, w jaki sposób mo na zbudować prostą własność w klasie. Ćwiczenie 2.11. Zbudujemy prostą klasę, której wykorzystanie w programie umo liwi w sposób bardzo elegancki i przejrzysty odczytywanie i zapisywanie danych w postaci nazwisk wybranych osób. W tym celu skorzystamy z definicji własności. Poniewa ogólnie przyjętą konwencją jest to, aby w tego typu programach posługiwać się pewnymi standardowymi przedrostkami dla zmiennych oraz funkcji, w dalszej części opisu będziemy wykorzystywać nazewnictwo angielskie — po to, by nie tworzyć mieszanki nazw polskich i angielskich (np. 5GV0CYKUMQ). 1. Na potrzeby naszego ćwiczenia samodzielnie zbudujemy własność, przy pomocy której będziemy w stanie odczytywać i przypisywać odpowiednie wartości (w tym przypadku łańcuchy znaków reprezentujące nazwiska i imiona osób). Ka da własność słu y do przechowywania wartości, zatem nale y zadeklarować związaną z nią zmienną (tzw. pole w klasie). Ogólnie przyjętą konwencją jest to, e zmienne mają takie same nazwy, jak związane z nimi własności, ale poprzedzone są literą (. W naszym programie w sekcji prywatnej definicji klasy 5VWFGPVU zadeklarujemy jedną taką zmienną typu #PUK5VTKPI, reprezentującą tablicę indeksującą nazwiska studentów. Dodatkowo w tej samej sekcji zadeklarujemy dwie funkcje (metody): )GV0COG , która w przyszłości będzie odczytywała przy pomocy indeksu imię i nazwisko wybranej osoby oraz 5GV0COG , za pomocą której będzie mo na przypisać odpowiedni łańcuch znaków (imię i nazwisko) do odpowiedniego indeksu w tablicy.
  • 38. 30 C++Builder 6. Ćwiczenia RTKXCVG #PUK5VTKPI (0COG=? #PUK5VTKPI )GV0COG KPV KPFGZ XQKF 5GV0COG KPV #PUK5VTKPI 2. Przechodzimy teraz do deklaracji samej własności. W tym celu nale y u yć słowa kluczowego AARTQRGTV[. Dla naszych potrzeb wystarczy, by własność słu yła wyłącznie do przekazywania danych (imion i nazwisk osób) przy pomocy indeksu. Własność zadeklarujemy w sekcji publicznej definicji klasy. Zdefiniowana przez nas własność 0COG będzie odczytywać aktualny stan tablicy (0COG przy pomocy dyrektywy TGCF, a następnie przekazywać (zapisywać) ją do funkcji 5GV0COG korzystając z dyrektywy YTKVG. RWDNKE 5VWFGPVU ]_ MQPUVTWMVQT `5VWFGPVU ]_ FGUVTWMVQT AARTQRGTV[ #PUK5VTKPI 0COG=KPV KPFGZ? ]TGCF)GV0COG YTKVG5GV0COG_ 3. Jednoparametrowa funkcja (metoda) )GV0COG ma bardzo prostą budowę i słu yć będzie do odpowiedniego indeksowania nazwisk: #PUK5VTKPI 5VWFGPVU)GV0COG KPV K ] TGVWTP (0COG=K? _ 4. Dwuparametrowa funkcja (metoda) 5GV0COG równie nie jest skomplikowana i przypisuje odpowiedniemu indeksowi tablicy ciąg znaków określony przez PCOGU. XQKF 5VWFGPVU5GV0COG KPV K EQPUV #PUK5VTKPI PCOGU ] (0COG=K?PCOGU _ Kompletny kod modułu Unit_07.cpp projektu Projekt_07.bpr wykorzystującego własność w klasie pokazany jest na wydruku 2.7. Wydruk 2.7. Moduł Unit07.cpp KPENWFG XENJ KPENWFG UVFKQJ KPENWFG EQPKQJ RTCIOC JFTUVQR ENCUU 5VWFGPVU ] RWDNKE 5VWFGPVU ]_ MQPUVTWMVQT MNCU[ `5VWFGPVU ]_ FGUVTWMVQT MNCU[ AARTQRGTV[ #PUK5VTKPI 0COG=KPV KPFGZ? ]TGCF)GV0COG YTKVG5GV0COG_ RTKXCVG #PUK5VTKPI (0COG=? #PUK5VTKPI )GV0COG KPV KPFGZ XQKF 5GV0COG KPV #PUK5VTKPI _ 2GTUQP GIGORNCT 2GTUQP QUQDC MNCU[ 5VWFGPVU
  • 39. Rozdział 2. C++ w pigułce 31 #PUK5VTKPI 5VWFGPVU)GV0COG KPV K ] TGVWTP (0COG=K? _ XQKF 5VWFGPVU5GV0COG KPV K EQPUV #PUK5VTKPI PCOGU ] (0COG=K?PCOGU _ KPV OCKP ] ENTUET 2GTUQP0COG=? 9CEGM ,CPMQYUMK Y[YQ WLG 2GTUQP5GV0COG 2GTUQP0COG=? ,CPGM 9CEMQYUMK 2GTUQP0COG=? ,QNC .QDWKPUMC HQT KPV K K K RWVU 2GTUQP0COG=K?EAUVT Y[YQ WLG 2GTUQP)GV0COG IGVEJ TGVWTP _ W głównej funkcji programu, w celu wyświetlenia odpowiednich łańcuchów znaków, u yliśmy metody EAUVT zwracającej wskaźnik (EJCT
  • 40. ) do pierwszego znaku łańcucha identyfikującego własność tablicową 0COG egzemplarza 2GTUQP klasy 5VWFGPVU. Mo na te zauwa yć, i u ycie w programie słowa AARTQRGTV[ oraz typu #PUK5VTKPI (elementy te nie są zdefiniowane w standardowym C++) wymaga włączenia do kodu modułu pliku nagłówkowego vcl.h (patrz rysunek 2.1). Funkcje przeładowywane Stosowanie w programie funkcji przeładowywanych (często te nazywanych funkcjami przecią anymi) w bardzo wielu wypadkach mo e znacznie ułatwić pisanie rozbudowa- nych programów. U ywanie funkcji przeładowywanych nierozerwalnie wią e się z tzw. polimorfizmem w C++. Polega on na zdefiniowaniu większej liczby funkcji posiadających taką samą nazwę, ale o ró nych postaciach listy parametrów. Mo liwość przecią ania funkcji jest w C++ czymś bardzo naturalnym i nie wymaga stosowania w ich deklaracjach specjalnych dyrektyw. Dla porównania przypomnijmy, e w Delphi funkcje czy procedury przecią ane zawsze nale y deklarować z dyrektywą QXGTNQCF. Pod względem u ywania funkcji przeładowywanych C++ nie generuje adnego nadmiarowego kodu w porównaniu z Object Pascalem. Ćwiczenie 2.12. Stworzymy program obliczający kolejne całkowite potęgi liczb ró nych typów. 1. Program zawierać będzie dwie podobne (ale nie takie same) funkcje o nazwie RQYGT (potęga), zwracające kolejne potęgi pobranego argumentu. Prototypy tych funkcji mo emy zapisać w sposób następujący:
  • 41. 32 C++Builder 6. Ćwiczenia WPUKIPGF KPV RQYGT WPUKIPGF KPV Z WPUKIPGF KPV [ FQWDNG RQYGT FQWDNG FZ WPUKIPGF NQPI F[ 2. Następnie zapiszmy ciała tych funkcji: WPUKIPGF KPV RQYGT WPUKIPGF KPV Z WPUKIPGF KPV [ ] WPUKIPGF KPV K HQT K K[ K
  • 42. Z TGVWTP _ FQWDNG RQYGT FQWDNG FZ WPUKIPGF NQPI F[ ] FQWDNG HQT WPUKIPGF KPV K KF[ K
  • 43. FZ TGVWTP _ Jak widać, nazwa RQYGT nie oznacza adnej konkretnej funkcji, a jedynie ogólny rodzaj działania wykonywanego na konkretnym typie liczb. 3. Wybór wersji funkcji odpowiadającej określonym potrzebom programisty jest wykonywany automatyczne przez kompilator, dzięki podaniu typu parametrów aktualnych wywoływanej funkcji RQYGT . Czynność tę wykonujemy wywołując odpowiednie funkcje w programie głównym. KPV OCKP ] ENTUET HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K EQWV GPFN HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K EQWV GPFN 0CEK PKL MNCYKU IGVEJ TGVWTP _ Jak łatwo zauwa yć, główną zaletą przeładowywania funkcji jest to, e bez problemu mo na wywoływać powiązane ze sobą zestawy instrukcji za pomocą tej samej nazwy, co pozwala, tak jak w pokazanym przypadku, zredukować dwie nazwy do jednej. Kompletny kod źródłowy głównego modułu projektu Projekt_08.bpr, wykorzystującego przeładowywane funkcje, zamieszczono na wydruku 2.8. Wydruk 2.8. Moduł Unit08.cpp KPENWFG KQUVTGCOJ KPENWFG EQPKQJ RTCIOC JFTUVQR RTQVQV[R[ RTG CFQY[YCPGL HWPMELK RQYGT WPUKIPGF KPV RQYGT WPUKIPGF KPV Z WPUKIPGF KPV [ FQWDNG RQYGT FQWDNG FZ WPUKIPGF NQPI F[
  • 44. Rozdział 2. C++ w pigułce 33 KPV OCKP ] ENTUET HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K EQWV GPFN HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K EQWV GPFN 0CEK PKL MNCYKU IGVEJ TGVWTP _ WPUKIPGF KPV RQYGT WPUKIPGF KPV Z WPUKIPGF KPV [ ] WPUKIPGF KPV K HQT K K[ K
  • 45. Z TGVWTP _ FQWDNG RQYGT FQWDNG FZ WPUKIPGF NQPI F[ ] FQWDNG HQT WPUKIPGF KPV K KF[ K
  • 46. FZ TGVWTP _ Kończąc rozwa ania o funkcjach przeładowywanych nale y zauwa yć, i teoretycznie mo emy nadawać identyczne nazwy funkcjom wykonującym ró ne działania, np. mno- enie, potęgowanie i logarytmowanie. Jednak z praktycznego punktu widzenia nie po- winniśmy postępować w ten sposób. Zawsze nale y dą yć do tego, aby przeładowywać funkcje wykonujące te same operacje. Ćwiczenie 2.13. Postaraj się zmodyfikować Projekt_08.bpr w taki sposób, aby bazował na pewnej klasie wykorzystującej omawiane funkcje. Niejednoznaczność Polimorfizm, którego przykładem jest mo liwość przeładowywania funkcji, stanowi jedną z wielkich zalet obiektowego języka C++, jednak równie niesie ze sobą (szczególnie dla mniej doświadczonych programistów) pewne pułapki. Jedną z nich jest niejedno- znaczność. Głównym źródłem niejednoznaczności w C++ są automatyczne konwersje typów. Uwa ny Czytelnik na pewno spostrzegł, w jaki sposób w programie przedstawionym na wydruku 2.8 wywoływane są funkcje nale ące do swoich prototypów:
  • 47. 34 C++Builder 6. Ćwiczenia WPUKIPGF KPV RQYGT WPUKIPGF KPV Z WPUKIPGF KPV [ RTQVQV[R HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K Y[YQ CPKG Y RTQITCOKG oraz: FQWDNG RQYGT FQWDNG FZ WPUKIPGF NQPI F[ RTQVQV[R HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K Y[YQ CPKG Y RTQITCOKG Funkcja RQYGT została przeładowana w taki sposób, e mo e pobierać argumenty w postaci par liczb typu WPUKIPGF KPV, WPUKIPGF KPV oraz FQWDNG, WPUKIPGF NQPI. Pierwsza instruk- cja wywołania funkcji RQYGT będzie jednoznaczna, gdy nie musi występować adna konwersja danych pomiędzy jej parametrami formalnymi i aktualnymi. Rozpatrzmy przy- padek, gdy funkcja RQYGT wywoływana jest z parametrem typu całkowitego WPUKIPGF KPV, będącego typem zmiennej sterującej K w pętli HQT , zaś jednym z jej parametrów formalnych (zdeklarowanym w jej prototypie) jest zmienna typu WPUKIPGF NQPI. W takiej sytuacji kompilator „nie wie”, czy zmienną taką przekształcić na typ NQPI KPV, czy NQPI FQWDNG. Je eli wywołalibyśmy funkcję w programie w sposób następujący: HQT WPUKIPGF KPV K K K EQWV GPFN @ K RQYGT K D úFPG Y[YQ CPKG Y RTQITCOKG mo emy spodziewać się wystąpienia przykrego komunikatu kompilatora: =% 'TTQT? 7PKVERR ' #ODKIWKV[ DGVYGGP RQYGT WPUKIPGF KPVWPUKIPGF KPV CPF RQYGT FQWDNGWPUKIPGF NQPI Aby uniknąć tego typu dwuznaczności, często uciekamy się do pewnego fortelu. Mianowicie wystarczy do liczby deklarowanej jako całkowita dodać wartość , aby kompilator do- konał jej automatycznej konwersji na typ zmiennopozycyjny. Funkcje ogólne Funkcjami ogólnymi posługujemy się w sytuacjach, w których wymagamy, aby definicja danej funkcji zawierała całość operacji wykonywanych na danych ró nych typów. Funkcję ogólną tworzymy przy pomocy słowa kluczowego VGORNCVG (szablon). Jego intuicyjne znaczenie jest bardzo trafne — szablon słu y do ogólnego opisu działań wykonywanych przez daną funkcję, zaś dalszymi szczegółami powinien zająć się ju sam kompilator C++. Szkielet definicji funkcji ogólnej rozpoczyna się właśnie od słowa VGORNCVG: VGORNCVG ENCUU 6[RCP[EJ 6[RYTCECP[ 0CYC(WPMELK NKUVC RCTCOGVTÎY ] KPUVTWMELG _
  • 48. Rozdział 2. C++ w pigułce 35 Ćwiczenie 2.14. Jak zapewne wiesz, jedną z właściwości języków C i C++ jest to, i wszystkie argumenty funkcji przekazywane są przez wartość. Wynika z tego, e wywoływana funkcja otrzymuje wartości swoich argumentów, a nie ich adresy. Mo na oczywiście spowodować, aby funkcja zmieniała wartości zmiennych w funkcji wywołującej. W tym celu funkcja wywołująca musi przekazać adresy swoich zmiennych. Zbudujemy prostą funkcję ogólną, która zmieniać będzie wartości dwóch zmiennych przekazywanych jej w instrukcji wywołania. Funkcja będzie porównywać dwie zmienne i jako wartość powrotną zwracać większą z liczb. 1. Zadeklarujemy prostą funkcję ogólną o nazwie OCZ . VGORNCVG ENCUU 6 6 OCZ 6 Z 6 [ ] TGVWTP Z [ ! Z [ _ Litera 6 oznacza tutaj nazwę zastępczą typu danych wykorzystywanych przez dwuparametrową funkcją OCZ . Zaletą podawania nazwy zastępczej jest to, e kompilator zawsze automatycznie zastąpi ją rzeczywistym typem danych w trakcie tworzenia konkretnej wersji funkcji. W funkcji tej wykorzystaliśmy operator warunkowy ! (pytajnik i dwukropek). Znaczenie jego jest następujące: ' ! ' ' Je eli wartość logiczna wyra enia (lub warunku) ' występującego po lewej stronie znaku ! jest prawdą (wartość ró na od zera), wówczas funkcja zwróci wartość wyra enia ' (w naszym przypadku Z), w przeciwnym razie wartością powrotną funkcji będzie wartość wyra enia ' występującego po znaku (w naszym przypadku [). 2. Wywołanie funkcji ogólnej OCZ w programie głównym nie powinno sprawić nam najmniejszych trudności. Na wydruku 2.9 pokazano kompletny kod źródłowy modułu Unit09.cpp projektu Projekt_09.bpr. Wydruk 2.9. Moduł Unit09.cpp KPENWFG KQUVTGCOJ KPENWFG EQPKQJ RTCIOC JFTUVQR VGORNCVG ENCUU 6 6 OCZ 6 Z 6 [ ] TGVWTP Z [ ! Z [ _ KPV OCKP ] FQWDNG Z [ EQWVUGVH KQUHKZGF EQWV OCZ Z [ GPFN IGVEJ TGVWTP _
  • 49. 36 C++Builder 6. Ćwiczenia W programie występuje dodatkowy szczegół, na który warto zwrócić uwagę. Mianowicie sposób formatowania liczb. W celu wyświetlenia wartości z większą liczbą cyfr po kropce, oddzielającej część całkowitą od części ułamkowej, wykorzystaliśmy metodę UGVH strumie- nia EQWV oraz metodę HKZGF (zwaną tutaj manipulatorem) klasy KQU. Z innymi sposobami przedstawiania liczb z u yciem funkcji składowych klasy KQU mo emy zapoznać się studiując pliki pomocy. Ćwiczenie 2.15. Programiści C przyzwyczajeni są do u ywania makrodefinicji. Definicję funkcji ogólnej OCZ mo emy zastąpić następującą makrodefinicją: FGHKPG OCZ Z [ Z [ ! Z [ Warto jednak zwrócić uwagę, i makrodefinicje nie mogą zmieniać wartości swoich pa- rametrów. Z tego względu pokazany sposób tworzenia makrodefinicji OCZ uwa a się obecnie za przestarzały. Programy tworzone w „czystym” C++ powinny (o ile jest to konieczne) u ywać funkcji ogólnych, umo liwiających operowanie na ró nych typach parametrów. Przetestuj samodzielnie projekt Projekt_09.bpr wykorzystując opisaną ma- krodefinicję. Przeładowywanie funkcji ogólnych Z potrzebą przeładowywania funkcji ogólnych mo emy spotkać się w sytuacji, w której istnieje konieczność zbudowania funkcji przeładowującej funkcję ogólną do określonego zestawu typów parametrów formalnych. Ćwiczenie 2.16. Jako prostą ilustrację metody przeładowania omawianej wcześniej funkcji ogólnej OCZ niech nam posłu y przykład, w którym za ądamy, aby wartością powrotną funkcji przeła- dowującej była mniejsza z dwu liczb całkowitych będących jej argumentami. 1. Jawne przeładowanie funkcji ogólnej OCZ mo e przybrać następującą postać: VGORNCVG ENCUU 6 6 OCZ 6 Z 6 [ ] TGVWTP Z [ ! Z [ _ RTG CFQYCPC YGTULC HWPMELK QIÎNPGL OCZ OCZ KPV Z KPV [ ] TGVWTP Z [ ! Z [ _ Cechą charakterystyczną przeładowywanych funkcji ogólnych jest to, e wszystkie ich wersje muszą wykonywać identyczne działania, zaś ró nić się mogą jedynie typami danych. Mogłoby się wydawać, e funkcja ogólna OCZ oraz jej wersja przeładowana wykonują ró ne działania, jednak z numerycznego punktu widzenia tak nie jest. Wynika to z faktu, i zarówno obliczanie większej, jak i mniejszej wartości
  • 50. Rozdział 2. C++ w pigułce 37 dwu wprowadzonych liczb jest z numerycznego punktu widzenia czynnością identyczną, gdy tak naprawdę wykonujemy jedynie operację porównania dwóch liczb, zaś jej „kierunek” nie ma najmniejszego znaczenia. 2. Funkcję ogólną oraz jej wersję przeładowaną wywołamy w programie tak, jak pokazano to na wydruku 2.10, gdzie wyraźnie zaznaczono z jakimi parametrami są one u ywane. Wydruk 2.10. Kod modułu Unit_10.cpp projektu Projekt_10.bpr KPENWFG KQUVTGCOJ KPENWFG EQPKQJ RTCIOC JFTUVQR VGORNCVG ENCUU 6 6 OCZ 6 Z 6 [ ] TGVWTP Z [ ! Z [ _ RTG CFQYCPC YGTULC HWPMELK QIÎNPGL OCZ OCZ KPV Z KPV [ ] TGVWTP Z [ ! Z [ _ KPV OCKP ] FQWDNG Z [ KPV K L EJCT C C EQWVUGVH KQUHKZGF 9[YQ CPKG HWPMELK QIÎNPGL OCZ RCTCOGVTCOK V[RW FQWDNG EQWV OCZ Z [ GPFN ,CYPG Y[YQ CPKG RTG CFQYCPGL HWPMELK OCZ RCTCOGVTCOK V[RW KPV /KOQ K HWPMELC RQUKCFC VCMæ UCOæ PCYú VQ LGFPCM YTCEC OPKGLU[ NKEDQYQ RCTCOGVT CMVWCNP[ EQWV OCZ K L GPFN 9[YQ CPKG HWPMELK QIÎNPGL OCZ RCTCOGVTCOK V[RW EJCT EQWV OCZ C GPFN IGVEJ TGVWTP _ Śledząc kod modułu bez trudu zauwa ymy, i w czasie kompilacji nie jest generowana wersja funkcji ogólnej OCZ posiadająca parametry typu całkowitego KPV i zwracająca mniejszy liczbowo parametr aktualny. Wynika to z bardzo prostego faktu, mianowicie w programie została ona przedefiniowana przez zwykłą funkcję OCZ KPV Z KPV [. Typ wyliczeniowy Typ wyliczeniowy pozwala programiście na zdefiniowanie nowego typu danych, gdzie ka demu elementowi zbioru zostanie przyporządkowana liczba odpowiadająca jego pozycji w zbiorze.
  • 51. 38 C++Builder 6. Ćwiczenia Typy wyliczeniowe definiuje się bardzo prosto. Po zarezerwowanym słowie GPWO podajemy nazwę nowego typu danych i znak równości, po którym następuje lista nazw nowego typu: GPWO V[RG ](KCV #WFK 1RGN_ Elementy tak zdefiniowanego typu są uporządkowane zgodnie z kolejnością ich wyliczania. Mamy te mo liwość jawnego przypisania wartości poszczególnym identyfikatorom za- deklarowanego typu: KPV OCKP ] GPWO V[RG ](KCV #WFK 1RGN 5WOC (KCV #WFK 1RGN_ EQWV .KEDC CWV Y UCNQPKG 5WOC IGVEJ TGVWTP _ Dziedziczenie Dziedziczenie jest jednym z najwa niejszych mechanizmów programowania zorientowa- nego obiektowo. Pozwala na przekazywanie właściwości klasy bazowej (ang. base class) klasom pochodnym (ang. derived classes). Oznacza to, e w prosty sposób mo na zbudować pewną hierarchię klas, uporządkowaną od najbardziej ogólnej do najbardziej szczegó- łowej. Na takiej właśnie hierarchii klas zbudowana jest w C++Builderze 6 zarówno bi- blioteka komponentów wizualnych VCL, jak i biblioteka międzyplatformowa CLX. Ogólną postać definicji klasy pochodnej zapisujemy z reguły w sposób następujący: ENCUU 0CYC0QYGL-NCU[ URGE[HKMCVQTAFQUVúRW 0CYC-NCU[KGFKEQPGL ] FGMNCTCELG UGMELK Y PQYGL MNCUKG _ 0CYC'IGORNCTC0QYGL-NCU[ QRELQPCNPKG Ćwiczenie 2.17. 1. Jako przykład zdefiniujemy klasę bazową o nazwie 8GJKENG (pojazd). Jak wiadomo, przeznaczenie danego pojazdu mo na szybko odgadnąć patrząc m.in. na liczbę i rodzaj jego kół. Zatem omawiana klasa zawierać będzie zmienną prywatną (9GGJNU określającą liczbę kół w pojeździe. Publiczna właściwość 9JGGNU (koła) słu y do odczytu i zapisu liczby kół. ENCUU 8GJKENG ] RWDNKE AARTQRGTV[ KPV 9JGGNU ]TGCF)GV9JGGNU YTKVG5GV9JGGNU_ RTKXCVG KPV (9JGGNU NKEDC MÎ KPV )GV9JGGNU XQKF 5GV9JGGNU KPV PWO _
  • 52. Rozdział 2. C++ w pigułce 39 2. Następnie wykorzystamy powy szą klasę bazową do definicji klasy reprezentującej pojazdy popularnie zwane „tirami”. Tiry będziemy rozró niać pod względem ich ładowności związanej z własnością %CTIQ (ładowność). ENCUU 6KT RWDNKE 8GJKENG ] RWDNKE AARTQRGTV[ KPV %CTIQ ]TGCF)GV%CTIQ YTKVG5GV%CTIQ_ RTKXCVG KPV (%CTIQ CFQYPQ è KPV )GV%CTIQ XQKF 5GV%CTIQ KPV PWO _ 3. Z kolei prywatna część definicji klasy 6KT posłu y nam do określenia klasy reprezentującej ju określone marki cię arówek .QTT[. GPWO V[RG ]5VG[GT /#0 8QNXQ_ ENCUU .QTT[ RTKXCVG 6KT ] RWDNKE AARTQRGTV[ GPWO V[RG .QTT[6[RG ]TGCF)GV.QTT[6[RG YTKVG5GV.QTT[6[RG_ XQKF 5JQY GPWO V[RG )GV.QTT[6[RG XQKF 5GV.QTT[6[RG GPWO V[RG 8 RTKXCVG GPWO V[RG (.QTT[6[RG OCTMC RQLCFW _ . GIGORNCT . MNCU[ .QTT[ FKGFKEæEGL RQ MNCUKG 6KT W klasie tej własność .QTT[6[RG musi być typu wyliczeniowego GPWO V[RG, je eli pojazdy te zechcemy w przyszłości rozró niać podając nazwę ich marek. 4. Specyfikator dostępu w klasie 6KT został u yty ze słowem RWDNKE. Oznacza to, i wszystkie publiczne elementy klasy dziedziczonej są elementami publicznymi w klasie pochodnej. W naszym przykładzie funkcje z klasy 6KT będą miały bezpośredni dostęp do funkcji składowych klasy 8GJKENG. Jednak funkcje klasy 6KT nie będą miały dostępu do zmiennej 9JGGNU z klasy 8GJKENG, gdy z oczywistych względów nie ma takiej potrzeby. 5. Specyfikator dostępu w klasie .QTT[ został u yty ze słowem RTKXCVG. Oznacza to, i wszystkie prywatne elementy klasy dziedziczonej są elementami prywatnymi w klasie pochodnej. W naszym przykładzie funkcje z klasy .QTT[ będą miały bezpośredni dostęp do zmiennej %CTIQ klasy 6KT. Postąpiliśmy w ten sposób, aby bez problemu w funkcji składowej 5JQY (poka ) klasy .QTT[ odwołać się bezpośrednio do zmiennej 9JGGNU z klasy 8GJKENG oraz %CTIQ klasy 6KT. W ten oto sposób wszystkie interesujące nas informacje uzyskamy wywołując w głównym programie jedynie funkcje składowe egzemplarza . klasy .QTT[, tak jak pokazano to na wydruku 2.11. Chocia program nasz składa się z trzech ró nych klas, zawierających szereg odrębnych funkcji składowych, to jedynymi obiektami, do których jawnie odwołujemy się w głównej funkcji OCKP , są funkcje składowe 5JQY oraz 5GV.QTT[6[RG egzemplarza . klasy .QTT[.
  • 53. 40 C++Builder 6. Ćwiczenia Wydruk 2.11. Kod modułu Unit_11.cpp projektu Projekt_11.bpr KPENWFG XENJ KPENWFG UVFKQJ KPENWFG EQPKQJ KPENWFG KQUVTGCOJ RTCIOC JFTUVQR ENCUU 8GJKENG ] RWDNKE AARTQRGTV[ KPV 9JGGNU ]TGCF)GV9JGGNU YTKVG5GV9JGGNU_ RTKXCVG KPV (9JGGNU NKEDC MÎ KPV )GV9JGGNU XQKF 5GV9JGGNU KPV PWO _ ENCUU 6KT RWDNKE 8GJKENG ] RWDNKE AARTQRGTV[ KPV %CTIQ ]TGCF)GV%CTIQ YTKVG5GV%CTIQ_ RTKXCVG KPV (%CTIQ CFQYPQ è KPV )GV%CTIQ XQKF 5GV%CTIQ KPV PWO _ GPWO V[RG ]5VG[GT /#0 8QNXQ_ ENCUU .QTT[ RTKXCVG 6KT ] RWDNKE AARTQRGTV[ GPWO V[RG .QTT[6[RG ]TGCF)GV.QTT[6[RG YTKVG5GV.QTT[6[RG_ XQKF 5JQY GPWO V[RG )GV.QTT[6[RG XQKF 5GV.QTT[6[RG GPWO V[RG 8 RTKXCVG GPWO V[RG (.QTT[6[RG OCTMC RQLCFW _ . GIGORNCT . MNCU[ .QTT[ FKGFKEæEGL RQ MNCUKG 6KT KPV 8GJKENG)GV9JGGNU ] TGVWTP (9JGGNU _ XQKF 8GJKENG5GV9JGGNU KPV PWO ] (9JGGNUPWO TGVWTP _ KPV 6KT)GV%CTIQ ] TGVWTP (%CTIQ _
  • 54. Rozdział 2. C++ w pigułce 41 XQKF 6KT5GV%CTIQ KPV PWO ] (%CTIQPWO TGVWTP _ GPWO V[RG .QTT[)GV.QTT[6[RG ] TGVWTP (.QTT[6[RG _ XQKF .QTT[5GV.QTT[6[RG GPWO V[RG 8 ] (.QTT[6[RG8 _ XQKF .QTT[5JQY ] UYKVEJ )GV.QTT[6[RG ] ECUG /#0 ] EQWV %Kú CTÎYMC OCTMK /#0 GPFN 9JGGNU EQWV .KEDC MÎ 9JGGNU GPFN %CTIQ EQWV CFQYPQ è %CTIQ VQP GPFN DTGCM _ ECUG 5VG[GT ] EQWV %Kú CTÎYMC OCTMK 5VG[GT GPFN 9JGGNU EQWV .KEDC MÎ 9JGGNU GPFN %CTIQ EQWV CFQYPQ è %CTIQ VQP GPFN DTGCM _ ECUG 8QNXQ ] EQWV %Kú CTÎYMC OCTMK 8QNXQ GPFN 9JGGNU EQWV .KEDC MÎ 9JGGNU GPFN %CTIQ EQWV CFQYPQ è %CTIQ VQP GPFN DTGCM _ _ TGVWTP _ KPV OCKP ] ENTUET .5GV.QTT[6[RG 5VG[GT .5JQY IGVEJ TGVWTP _
  • 55. 42 C++Builder 6. Ćwiczenia Analizując treść przedstawionego programu, natychmiast zauwa ymy, i główną zaletą stosowania zasady dziedziczenia klas jest mo liwość utworzenia jednej klasy bazowej wykorzystywanej następnie w definicjach klas pochodnych. Pokazaliśmy więc, w jaki sposób zdefiniować kilka bardzo podobnych klas uporządkowanych według określonej hierarchii. Funkcje wewnętrzne Jedną z zalet języka C++ jest mo liwość definiowania funkcji wewnętrznych, często te nazywanych po prostu funkcjami inline (ang. inline functions). Definicja funkcji wewnętrznej rozpoczyna się od słowa kluczowego KPNKPG: KPNKPG 6[R2QYTQVP[ GMNCTCELC(WPMELK .KUVC2CTCOGVTÎY Cechą charakterystyczną funkcji wewnętrznej jest to, i nie jest ona bezpośrednio wy- woływana w programie, natomiast jej kod umieszczany jest w miejscu, w którym ma być wykonany. Je eli funkcje wywołujemy w programie w sposób tradycyjny, zawsze nale y liczyć się z tym, i czynność ta będzie wymagała wykonania szeregu ró nych instruk- cji, takich jak umieszczenie jej argumentów w rejestrach procesora (lub na stosie), czy chocia by określenie wartości zwracanej. Inaczej cała sprawa przedstawia się w przypadku, gdy u ywamy funkcji wewnętrznych. Otó ich kod umieszczany jest bezpośrednio w funkcji wywołującej, przez co czynności takie jak odpowiednie umieszczenie w pamięci jej argu- mentów i określenie wartości powrotnej nie są wykonywane. Ćwiczenie 2.18. Jako prosty przykład wykorzystania funkcji wewnętrznych niech nam posłu y omawiane ju zagadnienie określania liczby kół w pojeździe. Zmodyfikujemy fragment kodu programu przedstawionego na wydruku 2.11 w ten sposób, aby w klasie 8GJKENG zdefiniowane zostały dwie funkcje wewnętrzne: )GV9JGGNU oraz 5GV9JGGNU , tak jak pokazano na wydruku 2.12. Wydruk 2.12. Kod modułu Unit_12.cpp projektu Projekt_12.bpr KPENWFG KQUVTGCOJ KPENWFG EQPKQJ RTCIOC JFTUVQR ENCUU 8GJKENG ] RWDNKE KPV )GV9JGGNU XQKF 5GV9JGGNU KPV PWO9JGGNU RTKXCVG KPV 9JGGNU NKEDC MÎ _8 KPNKPG KPV 8GJKENG)GV9JGGNU