You are on page 1of 26

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

C++Builder Borland
Developer Studio 2006.
Kompendium programisty
Autor: Andrzej Daniluk
ISBN: 83-246-0494-4
Format: B5, stron: 744

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Jeden z najnowszych produktw firmy Borland, C++Builder Borland Developer Studio


2006, to poczenie nowoczesnego jzyka programowania, jakim jest C++, biblioteki
komponentw wizualnych, zintegrowanego rodowiska programistycznego oraz
narzdzi sucych do modelowania oprogramowania. Pomimo e zaimplementowana
w C++Builder wersja jzyka C++ nie jest dokadnym odzwierciedleniem standardu
ANSI, rodowisko to zyskao due uznanie wrd najlepszych programistw,
doceniajcych jego uniwersalno i stabilno.
Ksika C++Builder Borland Developer Studio 2006. Kompendium programisty
przedstawia zasady programowania w jzyku C++ z wykorzystaniem narzdzia
C++Builder 2006. Opisuje zarwno samo rodowisko, jak i poszczeglne elementy
jzyka. Dziki niej nauczysz si korzysta z jzyka UML uywanego do projektowania
aplikacji oraz dowiesz si, jak realizowa projekty, wykorzystujc jzyk C++. Poznasz
take nowoczesne metodologie tworzenia oprogramowania za pomoc narzdzi typu RAD.
rodowisko C++Builder Borland Developer Studio 2006
Podstawy jzyka UML
Korzystanie z biblioteki STL
Obsuga wyjtkw
Operacje na systemie plikw
Programowanie wielowtkowe
Komponenty
Programowanie grafiki
Poznaj potg jzyka C++ i zdobd szczeglne umiejtnoci programowania

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

Wstp ................................................................................................................................................................11
Rozdzia 1.

rodowisko programisty IDE C++Builder Borland Developer Studio 2006 ..................... 15


Struktura gwnego menu ................................................................................................18
Pasek narzdzi Speed Bar ...........................................................................................47
Inspektor obiektw Object Inspector ....................................................................48
Widok struktury obiektw .........................................................................................49
Oglna posta programu pisanego w C++ .......................................................................50
Funkcja main() ...........................................................................................................52
Dyrektywa #include i prekompilacja .........................................................................53
Konsolidacja ..............................................................................................................54
Konfiguracja opcji projektu .......................................................................................54
Uruchamiamy program ..............................................................................................57
Oglna posta programu pisanego w C++Builderze BDS 2006 ......................................58
Formularz ...................................................................................................................59
Zdarzenia ....................................................................................................................61
Konsola czy formularz? ...................................................................................................64
Podsumowanie .................................................................................................................64

Rozdzia 2.

Jzyk modelowania, model dojrzaoci i proces projektowania ...............................................65


UML jako jzyk modelowania .........................................................................................65
Zawarto UML ...............................................................................................................67
Diagramy klas ............................................................................................................67
Diagramy obiektw ....................................................................................................72
Diagramy komponentw ............................................................................................73
Diagramy elementw zawierajcych struktur wewntrzn ......................................74
Diagramy pakietw ....................................................................................................75
Diagramy wdroenia ..................................................................................................76
Diagramy czynnoci ...................................................................................................76
Diagramy przypadkw uycia ...................................................................................79
Diagramy stanw .......................................................................................................80
Diagramy przebiegu ...................................................................................................82

D:\Roboczy Jarek\makiety poprawki i druku


programisty\_Spis treci.doc (29-05-06/14:06)

pdf\C++Builder

Borland

Developer

Studio

2006.

Kompendium
3

C++Builder Borland Developer Studio 2006. Kompendium programisty


Diagramy wsppracy ................................................................................................84
Diagramy komunikacji ...............................................................................................84
Diagramy harmonogramowania zada ......................................................................85
Mechanizmy rozszerzania ..........................................................................................85
Strategia modelowania i dokumentowania ......................................................................87
Model dojrzaoci .............................................................................................................88
Proces projektowania .......................................................................................................88
Nie tylko IID ..............................................................................................................90
Podsumowanie .................................................................................................................90

Rozdzia 3.

Podstawy jzyka C++ ...............................................................................................................................91


Dyrektywy preprocesora ..................................................................................................91
Dyrektywa #include ...................................................................................................91
Dyrektywa #define .....................................................................................................92
Dyrektywa #undef ......................................................................................................92
Dyrektywa #pragma hdrstop ......................................................................................92
Dyrektywa #pragma argsused ....................................................................................92
Dyrektywa #pragma inline .........................................................................................93
Dyrektywa #pragma option ........................................................................................93
Dyrektywa #pragma message ....................................................................................93
Dyrektywa #pragma package(smart_init) ..................................................................93
Dyrektywa #pragma resource "nazwa_pliku" ............................................................93
Dyrektywa #error .......................................................................................................94
Dyrektywy kompilacji warunkowej ...........................................................................94
Kategorie typw danych ...................................................................................................96
Podstawowe proste typy cakowite i rzeczywiste ..............................................................96
Typ int ........................................................................................................................97
Typ double .................................................................................................................97
Modyfikatory typw .........................................................................................................98
Typy danych Windows ...................................................................................................100
Typ Currency ..................................................................................................................101
Typ void .........................................................................................................................101
Typy logiczne .................................................................................................................101
Typy znakowe ................................................................................................................102
Typy acuchowe ...........................................................................................................102
Modyfikatory dostpu const i volatile ............................................................................103
Specyfikatory klas pamici ............................................................................................104
Specyfikator extern ..................................................................................................104
Specyfikator static ....................................................................................................105
Specyfikator register ................................................................................................105
Operatory ........................................................................................................................105
Typ wyliczeniowy ..........................................................................................................109
Sowo kluczowe typedef ................................................................................................109
Typ zbiorowy .................................................................................................................110
Deklarowanie tablic ........................................................................................................111
Instrukcje sterujce przebiegiem programu ...................................................................113
Instrukcja warunkowa if...else .................................................................................113
Instrukcja wyboru switch...case...break ...................................................................115
Instrukcja for ............................................................................................................116
Nieskoczona ptla for ............................................................................................118
Instrukcja iteracyjna do...while ................................................................................118
Instrukcja iteracyjna while .......................................................................................119
Instrukcja przerwania wykonywania ptli break .....................................................120

4 (29-05-06/14:06) D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\_Sp

Spis treci

Funkcja przerwania programu exit() ........................................................................121


Funkcja przerwania programu abort() .....................................................................122
Instrukcja kontynuacji programu continue ..............................................................122
Funkcje w C++ ...............................................................................................................122
Rekurencja ...............................................................................................................124
Przedefiniowywanie funkcji ....................................................................................125
Niejednoznaczno ..................................................................................................128
Konwencje wywoywania funkcji ............................................................................129
Specyfikatory konsolidacji funkcji ..........................................................................129
Wskazania i adresy .........................................................................................................129
Operatory wskanikowe ...........................................................................................133
Wskaniki i tablice ...................................................................................................133
Wielokrotne operacje porednie ..............................................................................135
Operatory new i delete .............................................................................................138
Dereferencja wskanika ...........................................................................................138
Wskaniki ze sowem kluczowym const .................................................................139
Wskaniki do funkcji ...............................................................................................140
Odwoania ......................................................................................................................145
Parametry odwoaniowe ...........................................................................................147
Zwracanie odwoa przez funkcje ...........................................................................149
Struktury .........................................................................................................................150
Przekazywanie struktur funkcjom ............................................................................152
Struktury zagniedone ............................................................................................153
Wskaniki do struktur ..............................................................................................155
Samodzielne tworzenie plikw nagwkowych .......................................................156
Unie ................................................................................................................................158
Klasy w C++ ..................................................................................................................159
Przedstawienie w UML ............................................................................................163
Konstruktor i destruktor ...........................................................................................164
Konstruktory kopiowania .........................................................................................166
Inne spojrzenie na klasy. Wasnoci ........................................................................167
Funkcje oglne .........................................................................................................170
Funkcje z dwoma typami oglnymi .........................................................................172
Przedefiniowywanie funkcji oglnych ....................................................................172
Klasy oglne ............................................................................................................174
Wzorce klas z wieloma oglnymi typami danych ...................................................176
Wzorzec auto_ptr .....................................................................................................177
Dziedziczenie ...........................................................................................................178
Powizania ...............................................................................................................183
Funkcje skadowe klas ze specyfikatorami const i volatile ............................................186
Funkcje wewntrzne ................................................................................................188
Realizacja przekazywania egzemplarzy klas funkcjom ...........................................190
Wskaniki do egzemplarzy klas ...............................................................................191
Operatory (.*) oraz (->*) ..........................................................................................193
Wskanik this ...........................................................................................................194
Przeadowywanie operatorw ........................................................................................195
Przeadowywanie jednoargumentowych operatorw ++ oraz ...............................196
Przeadowywanie operatorw (!) oraz (!=) ..............................................................199
Przeadowywanie dwuargumentowego operatora arytmetycznego + ......................202
Przeadowywanie operatora & .................................................................................204
Przeadowywanie operatora indeksowania tablic [ ] ...............................................205

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\_Spis treci.doc (29-05-06/14:06)

C++Builder Borland Developer Studio 2006. Kompendium programisty


Funkcje i klasy zaprzyjanione ......................................................................................208
Klasy wejcia-wyjcia jzyka C++ ................................................................................213
Obsuga plikw z wykorzystaniem klasy ios ...........................................................215
Tablicowe operacje wejcia-wyjcia ........................................................................217
Modele programistyczne ................................................................................................220
Programowanie sekwencyjne ...................................................................................221
Programowanie strukturalne ....................................................................................221
Programowanie proceduralne ..................................................................................222
Programowanie obiektowe .......................................................................................224
Programowanie zorientowane obiektowo ................................................................226
Programowanie generyczne .....................................................................................231
Programowanie aspektowe ......................................................................................231
Narzdzia metaprogramowania w C++ ...................................................................232
Programowanie oparte na skompilowanych moduach ...........................................234
Programowanie wielowtkowe ................................................................................235
Programowanie komponentowe ...............................................................................235
Podsumowanie ...............................................................................................................235

Rozdzia 4.

Wczesne oraz pne wizanie .............................................................................................................. 237


Odwoania i wskaniki do klas pochodnych ..................................................................237
Funkcje wirtualne w C++ ...............................................................................................240
Wirtualne klasy bazowe .................................................................................................243
Funkcje wirtualne w C++Builderze ...............................................................................247
Klasy abstrakcyjne w stylu biblioteki VCL ...................................................................251
Interfejsy .........................................................................................................................254
Zliczanie odwoa do interfejsu ...............................................................................255
Identyfikator interfejsu .............................................................................................256
Specyfikator __closure ...................................................................................................262
Obszary nazw .................................................................................................................265
Operator __classid ..........................................................................................................265
Funkcja Register() ..........................................................................................................266
Podsumowanie ...............................................................................................................266

Rozdzia 5.

Tablice ...........................................................................................................................................................267
Tablice dynamicznie alokowane w pamici ...................................................................267
Tablice dynamiczne ........................................................................................................270
Tablice otwarte ...............................................................................................................274
Tablice struktur ..............................................................................................................276
Tablice wskanikw do struktur ..............................................................................279
Odwoania do elementw tablicy wskanikw do struktur .....................................281
Podsumowanie ...............................................................................................................284

Rozdzia 6.

Biblioteka STL .......................................................................................................................................... 285


Iteratory ..........................................................................................................................285
Kontenery .......................................................................................................................286
vector ........................................................................................................................286
deque ........................................................................................................................289
list 289
slist ...........................................................................................................................290
set 290
map ...........................................................................................................................291
multiset .....................................................................................................................292
multimap ..................................................................................................................293

6 (29-05-06/14:06) D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\_Sp

Spis treci

hash_set ....................................................................................................................293
hash_map .................................................................................................................294
hash_multiset ...........................................................................................................295
hash_multimap .........................................................................................................296
Obiekty funkcyjne ..........................................................................................................297
Adaptery .........................................................................................................................300
Adaptery iteratorw .................................................................................................300
Adaptery kontenerw ...............................................................................................300
Adaptery obiektw funkcyjnych ..............................................................................302
Algorytmy ......................................................................................................................303
Alokatory ........................................................................................................................305
Valarray ..........................................................................................................................306
Podsumowanie ...............................................................................................................308

Rozdzia 7.

Zaawansowane operatory rzutowania typw .............................................................................. 309


Operator static_cast ........................................................................................................309
Operator dynamic_cast ...................................................................................................310
Operator const_cast ........................................................................................................313
Operator reinterpret_cast ................................................................................................316
Podsumowanie ...............................................................................................................317

Rozdzia 8.

Informacja czasu wykonania ................................................................................................................319


Klasa TObject .................................................................................................................319
Hierarchia wasnoci komponentw VCL .....................................................................323
Czas ycia komponentw ...............................................................................................324
Modu typeinfo.h ............................................................................................................326
Identyfikacja typw czasu wykonywania ......................................................................328
Tablica metod wirtualnych .............................................................................................330
Klasa TControl ...............................................................................................................331
Modyfikator __rtti ..........................................................................................................333
Podstawowe elementy GUI ............................................................................................334
Przydatne techniki modelowania GUI ...........................................................................335
Agregacje, kompozycje i powizania klas .....................................................................339
Podsumowanie ...............................................................................................................341

Rozdzia 9.

Obsuga wyjtkw .................................................................................................................................. 343


Standardowa obsuga wyjtkw .....................................................................................343
Strukturalna obsuga wyjtkw ......................................................................................348
Klasy wyjtkw ..............................................................................................................350
Zmienne globalne __throwExceptionName, __throwFileName, __throwLineNumber ...354
Zapisywanie nieobsuonych wyjtkw .........................................................................356
Transformowanie wyjtkw Windows ..........................................................................359
Podsumowanie ...............................................................................................................361

Rozdzia 10.

Obsuga plikw ......................................................................................................................................... 363


Klasy TDirectoryListBox, TFileListBox, TDriveComboBox .......................................363
Klasy TActionList, TOpenDialog i TSaveDialog ..........................................................365
Wasno Options klas TOpenDialog i TSaveDialog ....................................................372
Klasy TOpenTextFileDialog i TSaveTextFileDialog ....................................................374
Klasy TOpenPictureDialog i TSavePictureDialog ...........................................................374
Klasy TActionManager i TActionMainMenuBar ..........................................................377

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\_Spis treci.doc (29-05-06/14:06)

C++Builder Borland Developer Studio 2006. Kompendium programisty


Modu sysutils ................................................................................................................381
Operacje na plikach ..................................................................................................382
Atrybuty pliku ..........................................................................................................392
Okrelanie rozmiaru katalogu ..................................................................................397
Usuwanie katalogu ...................................................................................................397
Operacje na dyskach ................................................................................................398
Operacje na nazwach plikw ...................................................................................399
Wzajemne przeszukiwanie katalogw i plikw .......................................................400
Windows API .................................................................................................................403
Klasa TMemoryStream ..................................................................................................408
Klasa TFileStream ..........................................................................................................411
Tworzenie logw wyjtkw podczas kopiowania plikw .......................................414
Przesyanie plikw przez sie ........................................................................................415
Funkcja WinExec() ........................................................................................................419
Funkcja ShellExecuteEx() ..............................................................................................420
Pliki wymiany danych ....................................................................................................420
Kompilowanie plikw zasobw .....................................................................................422
Klasa TIniFile .................................................................................................................424
Drukowanie ....................................................................................................................428
Klasa TPrintDialog ..................................................................................................431
Dokumenty XML ...........................................................................................................432
Pliki i katalogi w Linuksie .............................................................................................434
Podsumowanie ...............................................................................................................436

Rozdzia 11.

acuchy ANSI .......................................................................................................................................437


Makrodefinicja VCL_IOSTREAM ................................................................................445
Znaki wielobajtowe ........................................................................................................448
Podsumowanie ...............................................................................................................449

Rozdzia 12.

Zmienne o typie modyfikowalnym w czasie wykonywania programu ............................451


Struktura TVarData ........................................................................................................451
Klasa TCustomVariantType ...........................................................................................455
Modu variants ................................................................................................................457
Tablice wariantowe ........................................................................................................459
Wariantowe tablice otwarte ............................................................................................465
Klient OLE .....................................................................................................................468
Modu VarCmplx ...........................................................................................................471
Liczby zespolone, paszczyzna liczbowa, modu i argument liczby .......................471
Podsumowanie ...............................................................................................................478

Rozdzia 13.

Funkcje FPU i systemowe ....................................................................................................................479


Funkcje FPU ...................................................................................................................479
Struktura SYSTEM_INFO .............................................................................................485
Klasa THeapStatus .........................................................................................................488
Identyfikator GUID ........................................................................................................491
Klasa TRegistry ..............................................................................................................493
Klasa TRegistryIniFile ...................................................................................................496
Podsumowanie ...............................................................................................................497

Rozdzia 14. Elementy wielowtkowoci .................................................................................................................499


Wtki i procesy ...............................................................................................................499
Funkcja _beginthread() ..................................................................................................501
Funkcja _beginthreadNT() .............................................................................................504

8 (29-05-06/14:06) D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\_Sp

Spis treci

Funkcja _beginthreadex() ...............................................................................................509


Funkcja BeginThread() ..................................................................................................509
Zmienne lokalne wtku ..................................................................................................514
Klasa TThread ................................................................................................................516
Synchronizacja wtkw ..................................................................................................522
Sekcje krytyczne ............................................................................................................527
Wzajemne wykluczenia ..................................................................................................529
Uruchamianie zewntrznych plikw wykonywalnych ..................................................531
Wielowtkowe operacje na dyskach, katalogach i plikach ............................................532
Zmienna IsMultiThread ..................................................................................................535
Podsumowanie ...............................................................................................................536

Rozdzia 15.

Liczby pseudolosowe .............................................................................................................................. 537


Funkcje randomize() i random() ....................................................................................538
Losowanie z powtrzeniami ...........................................................................................543
Losowanie bez powtrze ..............................................................................................546
Generatory czciowo uporzdkowane ..........................................................................552
Szyfrowanie ....................................................................................................................560
Podsumowanie ...............................................................................................................561

Rozdzia 16.

Konwersje wielkoci liczbowych ....................................................................................................... 563


Podsumowanie ...............................................................................................................587

Rozdzia 17.

Wprowadzenie do grafiki ..................................................................................................................... 589


Barwne modele ...............................................................................................................590
Ptno .............................................................................................................................593
Mapy bitowe ...................................................................................................................598
JPEG ...............................................................................................................................603
JPEG 2000 ...............................................................................................................606
Obraz video ....................................................................................................................607
Drukowanie grafiki ........................................................................................................611
Komponent TChart .........................................................................................................612
Podsumowanie ...............................................................................................................615

Rozdzia 18.

Komponentowy model C++Buildera ............................................................................................... 617


Tworzymy nowy komponent .........................................................................................617
Modyfikacja istniejcego komponentu z biblioteki VCL ..............................................626
Komponenty graficzne ...................................................................................................631
Harmonogramowanie zada ...........................................................................................637
Usuwanie komponentw z pakietu ................................................................................644
Komponenty generyczne ................................................................................................645
Podsumowanie ...............................................................................................................648

Rozdzia 19.

Biblioteki DLL .........................................................................................................................................649


czenie statyczne. Cz I ............................................................................................650
czenie statyczne. Cz II ..........................................................................................652
adowanie i zwalnianie bibliotek w czasie dziaania programu ....................................655
Funkcja DllEntryPoint() .................................................................................................658
Klasy jako elementy bibliotek DLL ...............................................................................661
Bazowe adresy adowania ..............................................................................................664
Okrelanie adresw funkcji ............................................................................................664
Komponenty i biblioteki DLL ........................................................................................667

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\_Spis treci.doc (29-05-06/14:06)

10

C++Builder Borland Developer Studio 2006. Kompendium programisty


Pakiety ............................................................................................................................670
Zmienna IsLibrary ..........................................................................................................675
Podsumowanie ...............................................................................................................675

Dodatek A

GRAPPLE .................................................................................................................................................677
Zbieranie wymaga ........................................................................................................678
Modelowanie urzdzenia .........................................................................................678
Protok ....................................................................................................................678
Interakcje ..................................................................................................................679
Identyfikacja wsppracujcych systemw ..............................................................679
Analiza ...........................................................................................................................680
Przypadki uycia ......................................................................................................680
Zmiany stanu systemu ..............................................................................................681
Wstpny model klas programu kontrolujcego zewntrzny system wbudowany ...682
Projektowanie .................................................................................................................682
Statyczny model klas programu kontrolujcego zewntrzny system wbudowany .....683
Diagram artefaktw .................................................................................................684
Diagramy czynnoci .................................................................................................684
Kodowanie .....................................................................................................................685
Wdroenie ......................................................................................................................690
Graficzny interfejs uytkownika ....................................................................................691
Kodowanie ...............................................................................................................693
Podsumowanie ...............................................................................................................693

Dodatek B

Together ....................................................................................................................................................... 695


Literatura ....................................................................................................................................................707
Skorowidz .....................................................................................................................................................711

10 (29-05-06/14:06) D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\_S

W analizie i projektowaniu zorientowanym obiektowo wystpuj dwa bardzo wane pojcia:


wczesne oraz pne wizanie. Z wczesnym wizaniem (ang. early binding) mamy do czynienia
w sytuacjach, gdy funkcje w trakcie kompilacji programu wie si z okrelonymi obiektami.
Przykadem wczesnego wizania bd np. sytuacje, w ktrych w gwnej funkcji main() wywoujemy funkcje standardowe i przeadowane oraz funkcje przedefiniowywanych standardowych
operatorw. Sytuacje, gdy wywoywane funkcje wizane s z okrelonymi obiektami w trakcie dziaania programu, okrelamy mianem pnego wizania (ang. late binding). Przykadem
pnego wizania s klasy pochodne, funkcje wirtualne, klasy polimorficzne i abstrakcyjne.
Wielk zalet technik zwizanych z pnym wizaniem jest moliwo stworzenia prawdziwego interfejsu uytkownika wraz z odpowiedni bibliotek klas, ktr mona niemal swobodnie uzupenia i modyfikowa.

Na podstawie wiadomoci przedstawionych w poprzednich rozdziaach miao moemy wywnioskowa, i wskanik okrelonego typu nie moe wskazywa na dane odmiennych typw. Niemniej jednak od tej reguy istnieje pewne bardzo wane odstpstwo. Rozpatrzmy sytuacj, w ktrej
zaimplementowalimy w programie pewn klas zwan klas bazow oraz klas z niej dziedziczc czyli klas pochodn (potomn). Okazuje si, e wskaniki do klasy bazowej mog
rwnie w okrelonych sytuacjach wskazywa na reprezentantw lub elementy klasy pochodnej.
Zamy, i w programie zaimplementowalimy klas bazow TStudent z publiczn funkcj
skadow przechowujc nazwisko pewnego studenta. Nastpnie stworzymy klas pochodn
TEgzamin z publiczn funkcj skadow przechowujc ocen, jak otrzymaa dana osoba z egzaminu z wybranego przedmiotu. W funkcji main() zadeklarujemy zmienn infoStudent jako
wskanik do klasy TStudent:
TStudent *infoStudent;

D:\Roboczy Jarek\makiety poprawki


programisty\04.doc (29-05-06/14:07)

druku

pdf\C++Builder

Borland

Developer

Studio

2006.

Kompendium
237

238

C++Builder Borland Developer Studio 2006. Kompendium programisty

Zadeklarujmy rwnie po jednym egzemplarzu klas TStudent i TEgzamin:


TStudent student;
TEgzamin egzamin;

Okazuje si, e zmienna deklarowana jako wskanik do typu bazowego TStudent moe wskazywa nie tylko na obiekty klasy bazowej, ale rwnie i pochodnej:
infoStudent=&student;
infoStudent=&egzamin;

Za pomoc tak okrelonego wskanika infoStudent mona uzyska dostp do wszystkich elementw klasy TEgzamin odziedziczonych po klasie TStudent, tak jak pokazano to na listingu 4.1.
Listing 4.1. Kod gwnego moduu Unit_R4_01.cpp projektu Projekt_R4_01.bdsproj wykorzystujcego wskaniki
i odwoania do typw pochodnych
#include <iostream>
#pragma hdrstop
using namespace std;
class TStudent
// klasa bazowa
{
char nazwisko[40];
public:
void __fastcall jakiStudent(char *s)
{strcpy(nazwisko, s);}
void __fastcall pokazN() {cout << nazwisko << endl;}
};
//--------------------------------------------------------class TEgzamin: public TStudent
// klasa pochodna
{
char ocena[5];
public:
void __fastcall egzaminInformatyka(char *e)
{strcpy(ocena, e);}
void __fastcall pokazE() {cout << ocena << endl;}
};
//--------------------------------------------------------int main()
{
// wskanik do klasy TStudent (bazowej)
TStudent *infoStudent;
// student-egzemplarz klasy TStudent
TStudent student;
// wskanik do klasy TEgzamin (pochodnej)
TEgzamin *eInfoStudent;
// egzamin-egzemplarz klasy TEgzamin
TEgzamin egzamin;
// wskanik infoStudent wskazuje na egzemplarz
// klasy TStudent
infoStudent=&student;

238(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

239

infoStudent->jakiStudent("Wacek Jankowski");
// wskanik infoStudent wskazuje na egzemplarz
// klasy Tegzamin, bdcej klas pochodn wzgldem
// klasy bazowej TStudent
infoStudent=&egzamin;
infoStudent->jakiStudent("Janek Wackowski");
// sprawdzenie poprawno ci przypisae
student.pokazN();
egzamin.pokazN();
cout << endl;
// funkcje egzaminInformatyka() i pokazE() s
// elementami klasy pochodnej. Dostp do nich uzyskujemy
// za pomoc wskanika eInfoStudent
eInfoStudent = &egzamin;
eInfoStudent->egzaminInformatyka("Egz. Informatyka 2.5");
infoStudent->pokazN();
eInfoStudent->pokazE();
cout << endl;
// uzyskanie dostpu do funkcji skadowej klasy pochodnej
// za pomoc wskanika do klasy bazowej
((TEgzamin *)infoStudent)->pokazE();
cin.get();
return 0;

}
//---------------------------------------------------------

ledzc powysze zapisy, z atwoci przekonamy si, i wskanik do klasy bazowej moe
rwnie dobrze wskazywa na te elementy klasy pochodnej, ktre s zdefiniowane rwnie w klasie bazowej, z tego wzgldu, e klasa TEgzamin dziedziczy publiczne elementy klasy TStudent.
Jednak, uywajc w prosty sposb wskanika do klasy bazowej, nie mona uzyska dostpu
do tych elementw, ktre wystpuj jedynie w klasie pochodnej. W przypadku, gdy zadalibymy uzyskania dostpu np. do funkcji skadowej pokazE() klasy pochodnej, naleaoby wykorzysta zmienn studentInfo bdc jawnym wskanikiem do klasy TEgzamin. Jeeli mimo
wszystko kto zdecydowaby si, aby za pomoc wskanika do klasy bazowej uzyska dostp
do jakiego elementu klasy pochodnej, bdzie musia wykona w odpowiedni sposb operacj
rzutowania typw:
((TEgzamin *)infoStudent)->pokazE();

Poprzez wykorzystanie zewntrznej pary nawiasw informujemy kompilator, i rzutowanie


czone jest ze wskanikiem infoStudent, a nie z wartoci funkcji pokazE(). Wystpowanie wewntrznej pary nawiasw okrela sytuacj, w ktrej wskanik infoStudent do klasy bazowej
rzutowany jest na typ klasy pochodnej TEgzamin.

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

239

240

C++Builder Borland Developer Studio 2006. Kompendium programisty

Funkcj wirtualn (ang. virtual function) nazywamy tak funkcj, ktra jest zadeklarowana
w klasie bazowej za pomoc sowa kluczowego virtual, a nastpnie w takiej samej postaci
definiowana rwnie w klasach pochodnych. Funkcje takie bardzo czsto okrela si mianem
funkcji kategorii virtual. Ponownie definiujc funkcj wirtualn w klasie pochodnej, moemy (ale
nie musimy) powtrnie umieszcza sowo virtual przed jej nazw. Funkcje wirtualne maj
bardzo ciekaw waciwo. Charakteryzuj si mianowicie tym, i podczas wywoywania dowolnej z nich za pomoc odwoania lub wskanika do klasy bazowej wskazujcego na egzemplarz klasy pochodnej, aktualna wersja wywoywanej funkcji kadorazowo ustalana jest w trakcie
wykonywania programu z rozrnieniem typu wskazywanej klasy. Klasy, w ktrych zdefiniowano
jedn lub wicej funkcji wirtualnych, nazywamy klasami polimorficznymi.
Jako praktyczny sposb wykorzystania klas polimorficznych rozpatrzmy przykad, gdzie zadeklarowano nieskomplikowan klas bazow TBazowa z funkcj pokazB() kategorii virtual,
ktrej jedynym zadaniem jest wywietlenie odpowiedniego tekstu. Poniewa funkcja jest rzeczywicie funkcj wirtualn, moemy j z powodzeniem powtrnie zdefiniowa (tzn. zdefiniowa jej kolejn wersj) w klasie pochodnej Tpochodna, dziedziczcej publiczne elementy klasy
TBazowa. Sytuacj t ilustruje listing 4.2.
Listing 4.2. Kod gwnego moduu Unit_R4_02.cpp projektu Projekt_R4_02.bdsproj jako przykad wykorzystania
klas polimorficznych
#include <iostream>
#pragma hdrstop
using namespace std;
class TBazowa {
public:
__fastcall TBazowa() {pokazB();}
// konstruktor
virtual void __fastcall pokazB()
{cout << "Jestem klasa bazowa" << endl; }
};
//--------------------------------------------------------class TPochodna : public TBazowa {
public:
__fastcall TPochodna() {pokazB();}
// konstruktor
/*virtual*/ void __fastcall pokazB()
{cout << "Jestem klasa pochodna" << endl;}
};
//--------------------------------------------------------int main()
{
TPochodna pochodna;
// wywoanie funkcji pokazB()
cin.get();
return 0;
}
//---------------------------------------------------------

240(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

241

Jak atwo zauway, w celu wywoania funkcji pokazB() w gwnej funkcji main() zawarto
jedynie deklaracj egzemplarza klasy pochodnej. Wynika to z faktu, i zarwno klasa bazowa,
jak i pochodna zawieraj odpowiednio zaimplementowane konstruktory.
Na listingu 4.3 zamieszczono przykad ilustrujcy ide posugiwania si wskanikami do klas
polimorficznych, co w efekcie pozwala na pominicie jawnych deklaracji konstruktorw odpowiednich klas.
Listing 4.3. Kod gwnego moduu Unit_R4_03.cpp projektu Projekt_R4_03.bdsproj wykorzystujcego wskaniki
do klas polimorficznych
#include <iostream>
#pragma hdrstop
using namespace std;
class TBazowa {
public:
virtual void __fastcall pokazB()
{cout << "Jestem klasa bazowa" << endl; }
};
//--------------------------------------------------------class TPochodna : public TBazowa {
public:
/*virtual*/ void __fastcall pokazB()
{cout << "Jestem klasa pochodna" << endl;}
};
//--------------------------------------------------------int main()
{
TBazowa bazowa;
TBazowa *ptrBazowa;
TPochodna pochodna;
ptrBazowa = &bazowa;
ptrBazowa->pokazB();
// wywoanie funkcji pokazB() klasy TBazowa
ptrBazowa=&pochodna;
ptrBazowa->pokazB();
// wywoanie funkcji pokazB() klasy TPochodna
cin.get();
return 0;
}
//---------------------------------------------------------

W podanym przykadzie w klasie bazowej definiowana jest funkcja wirtualna pokazB(), po czym
jej kolejna wersja zdefiniowana jest wzgldem klasy pochodnej. W gwnej funkcji main()
zawarto w kolejnoci deklaracj egzemplarza bazowa klasy bazowej, wskanika ptrBazowa do
klasy bazowej i egzemplarza pochodna klasy pochodnej. Dziki instrukcjom:
ptrBazowa = &bazowa;

zmienna ptrBazowa uzyskuje adres egzemplarza klasy bazowej, co w konsekwencji pozwala na


wykorzystanie jej do wywoania funkcji pokazB() z klasy bazowej:
ptrBazowa->pokazB();

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

241

242

C++Builder Borland Developer Studio 2006. Kompendium programisty

W analogiczny sposb mona dokona wywoania funkcji pokazB() klasy pochodnej, posugujc
si adresem egzemplarza klasy pochodnej. Poniewa funkcja pokazB() jest w swoich klasach
funkcj wirtualn, zatem w trakcie dziaania programu decyzja o tym, ktra wersja tej funkcji
jest aktualnie wywoywana, zapada na podstawie okrelenia typu egzemplarza klasy aktualnie
wskazywanego przez wskanik ptrBazowa.
Podczas pracy z funkcjami wirtualnymi moliwe jest rwnie wykorzystywanie parametru jako
odwoania do klasy bazowej. Odpowiednio konstruowane odwoania do klasy bazowej umoliwiaj wywoanie funkcji wirtualnej z jednoczesnym przekazaniem jej argumentu. Przedstawiony na listingu 4.4 program jest modyfikacj algorytmu z poprzedniego wiczenia. Zadeklarowano w nim klas bazow, dwie klasy pochodne oraz funkcj przeadowan, zawierajc
poprzez parametr formalny x odwoanie do klasy bazowej:
//--------------------------------------------------------void __fastcall pokazB(TBazowa &x)
// odwoanie do klasy bazowej
{
x.pokazB();
return;
}
//---------------------------------------------------------

Dziki tak skonstruowanemu odwoaniu aktualna wersji funkcji pokazB(), ktra powinna by
w danym momencie dziaania programu wywoana, ustalana jest w gwnej funkcji main() na
podstawie typu, do ktrego odwouje si jej parametr aktualny.
Listing 4.4. Kod gwnego moduu Unit_R4_04.cpp projektu Projekt_R4_04.bdsproj wykorzystujcego odwoanie
do klasy polimorficznej
#include <iostream>
#pragma hdrstop
using namespace std;
class TBazowa {
public:
virtual void __fastcall pokazB()
{cout << "Jestem klasa bazowa" << endl; }
};
//--------------------------------------------------------class TPochodna1 : public TBazowa {
public:
/*virtual*/ void __fastcall pokazB()
{cout << "Jestem 1 klasa pochodna" << endl;}
};
//--------------------------------------------------------class TPochodna2 : public TBazowa {
public:
/*virtual*/ void __fastcall pokazB()
{cout << "Jestem 2 klasa pochodna" << endl;}
};
//---------------------------------------------------------

242(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

243

void __fastcall pokazB(TBazowa &x)


// odwoanie do klasy bazowej
{
x.pokazB();
return;
}
//--------------------------------------------------------int main()
{
TBazowa bazowa;
TPochodna1 pochodna1;
TPochodna2 pochodna2;
pokazB(bazowa);
// wywoanie funkcji pokazB() klasy TBazowa
pokazB(pochodna1);
// wywoanie funkcji pokazB() klasy TPochodna1
pokazB(pochodna2);
// wywoanie funkcji pokazB() klasy TPochodna2
cin.get();
return 0;
}
//---------------------------------------------------------

Wskazwka
Bardzo czsto funkcje zawierajce odwoania do klas polimorficznych maj
(chocia niekoniecznie) takie same nazwy, jak funkcje wirtualne wzgldem danej
klasy. Chocia funkcje te mog mie takie same nazwy, nie naley utosamia ich
z funkcjami przeadowanymi. Pomidzy konstrukcj funkcji przeadowywanych
i ponownym definiowaniem funkcji wirtualnych istniej powane rnice, np. prototypy
funkcji wirtualnych musz by identyczne, funkcje przeadowane za maj rn liczb
lub typ parametrw. Z tego powodu ponowne definiowanie funkcji wirtualnych nazywa
si przykrywaniem lub nadpisywaniem funkcji.

Tematem poprzedniego podrozdziau byy funkcje wirtualne, czyli funkcje deklarowane ze sowem kluczowym virtual. Z przedstawionych przykadw atwo wywnioskujemy, i wielk
ich zalet jest to, e s one odpowiednio przykrywane w klasach pochodnych. Jednak w jzyku C++ sowo virtual posiada jeszcze jedno znaczenie, suy mianowicie do deklarowania
tzw. wirtualnych klas bazowych.
Rozpatrzmy sytuacj, w ktrej potrzebujemy zdefiniowa w programie pewn klas bazow
TBazowa, dwie klasy pochodne TPochodna1 i TPochodna2 dziedziczce po klasie bazowej i dodatkowo trzeci klas pochodn TPochodna3, dziedziczc elementy publiczne klas TPochodna1
i TPochodna2. W kadej z klas zdefiniujmy po jednej funkcji zwracajcej pewn warto cakowit. Przyjte zaoenia ilustruje rysunek 4.1 oraz listing 4.5.

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

243

244

C++Builder Borland Developer Studio 2006. Kompendium programisty

Rysunek 4.1. Idea poziomego dziedziczenia klas. Klasa TPochodna3 dziedziczy poziomo (wielokrotnie)
po klasach TPochodna1 i TPochodna2
Listing 4.5. Kod gwnego moduu Unit_R4_05.cpp projektu Projekt_R4_05.bdsproj wykorzystujcego
standardowe klasy bazowe
// Program nie zostanie skompilowany !
#include <iostream>
#include <vcl>
#pragma hdrstop
using namespace std;
class TBazowa {
public:
int i;
int __fastcall pokazB()
{cout << "Jestem klasa bazowa" << endl;
return i; }
};
//--------------------------------------------------------class TPochodna1 : public TBazowa {
public:
int j;
int __fastcall pokazP1()
{cout << "Jestem 1 klasa pochodna" << endl;
return j;}
};
//---------------------------------------------------------

244(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

245

class TPochodna2 : public TBazowa {


public:
int k;
int __fastcall pokazP2()
{cout << "Jestem 2 klasa pochodna" << endl;
return k;}
};
//--------------------------------------------------------// klasa TPochodna3 dziedziczy klasy TPochodna1 i TPochodna2,
// i zawiera dwie kopie klasy TBazowa
class TPochodna3 : public TPochodna1, public TPochodna2 {
public:
int l;
int __fastcall pokazP3()
{cout << "Jestem 3 klasa pochodna" << endl;
return l;}
};
//--------------------------------------------------------int main()
{
TPochodna3 klasa;
klasa.i = 100;
klasa.j = 200;
klasa.k = 300;
klasa.l = 400;
cout << klasa.pokazP1() << endl;
cout << klasa.pokazP2() << endl;
cout << klasa.pokazP3() << endl;
cin.get();
return 0;
}
//---------------------------------------------------------

Podczas prby uruchomienia powyszego programu spotka nas przykra niespodzianka polegajca na tym, e program si po prostu nie skompiluje! Wynika to z faktu, i jego konstrukcja jest niejednoznaczna, poniewa wywoanie:
klasa.i = 100;

jest dla kompilatora niejednoznaczne:


[C++ Error] [nit_E4_05.cpp(44): E2014 (ember is ambiguous:
'TBazowa::i' and 'TBazowa::i'

z tego powodu, e kady egzemplarz klasy TPochodna3 zawiera dwie kopie elementw skadowych klasy TBazowa. Poniewa w tej sytuacji istniej dwie kopie zmiennej i (deklarowanej
w klasie bazowej), kompilator nie ma najmniejszej wiedzy na temat, ktr kopi zmiennej ma
wykorzysta t odziedziczon przez klas TPochodna1 czy t z klasy TPochodna2.
Jeeli dwie lub wiksza liczba klas dziedziczy z tej samej klasy bazowej, moemy zapobiec
sytuacji, w ktrej kopia klasy bazowej jest powielana w klasach potomnych w sposb niekontrolowany. Istnieje kilka sposobw, aby przeciwdziaa takiemu samopowielaniu si klasy
bazowej. Najprostszym rozwizaniem jest zadeklarowanie klas pochodnych jako klas kategorii virtual, tak jak pokazano to na listingu 4.6.

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

245

246

C++Builder Borland Developer Studio 2006. Kompendium programisty

Listing 4.6. Kod gwnego moduu Unit_R4_06.cpp projektu Projekt_R4_06.bdsproj wykorzystujcego


wirtualne klasy bazowe
#include <iostream>
#include <vcl>
#pragma hdrstop
using namespace std;
class TBazowa {
public:
int i;
int __fastcall pokazB()
{cout << "Jestem klasa bazowa" << endl;
return i; }
};
//--------------------------------------------------------// klasa TPochodna1 dziedziczy klas TBazowa jako wirtualn
class TPochodna1 : virtual public TBazowa {
public:
int j;
int __fastcall pokazP1()
{cout << "Jestem 1 klasa pochodna" << endl;
return j;}
};
//--------------------------------------------------------// klasa TPochodna2 dziedziczy klas TBazowa jako wirtualn
class TPochodna2 : virtual public TBazowa {
public:
int k;
int __fastcall pokazP2()
{cout << "Jestem 2 klasa pochodna" << endl;
return k;}
};
//--------------------------------------------------------// klasa TPochodna3 dziedziczy klasy TPochodna1 i TPochodna2,
// ale zawiera jedn kopi klasy TBazowa
class TPochodna3 : public TPochodna1, public TPochodna2 {
public:
int l;
int __fastcall pokazP3()
{cout << "Jestem 3 klasa pochodna" << endl;
return l;}
};
//--------------------------------------------------------int main()
{
TPochodna3 klasa;
klasa.i = 100;
klasa.j = 200;
klasa.k = 300;
klasa.l = 400;
cout << klasa.pokazP1() << endl;
cout << klasa.pokazP2() << endl;

246(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

247

cout << klasa.pokazP3() << endl;


cin.get();
return 0;

}
//---------------------------------------------------------

Testujc przedstawiony algorytm, natychmiast zauwaymy, i w klasie TPochodna3 istnieje


teraz ju tylko jedna kopia klasy bazowej, gdy klasy TPochodna1 i TPochodna2 dziedzicz klas
bazow jako klas wirtualn, co skutkuje utworzeniem tylko jednej kopii klasy TBazowa.

Wskazwka
Klasy wirtualne naley wykorzystywa tylko wtedy, gdy w programie istnieje
konieczno wielokrotnego dziedziczenia klas. Gdy klasa bazowa dziedziczona
jest jako wirtualna, w programie tworzona jest tylko jedna jej kopia. Przez pojcie
wielokrotnego dziedziczenia (dziedziczenia poziomego) rozumiemy sytuacj,
w ktrej jedna klasa jednoczenie dziedziczy po wikszej liczbie klas.

W C++Builderze, traktowanym jako kompletne rodowisko programistyczne, istnieje klasa


TobTect, bdca podstawow klas, po ktrej dziedzicz wszystkie inne. Czsto mwimy, e
klasa ta jest przodkiem wszystkich typw obiektowych C++Buildera, co midzy innymi oznacza, e na przykad zmienna wskazujca na typ TObTect moe wskazywa na obiekt dowolnej
innej klasy dziedziczcej po TObTect. Klasa TObTect nie zawiera adnych jawnych elementw
skadowych. Posiada natomiast elementy przechowujce wskaniki do tzw. tablicy metod wirtualnych VMT.
Jak zapewne wywnioskowalimy z lektury niniejszego rozdziau, klasa bazowa (najbardziej
oglna) i klasy pochodne (klasy szczegowe) tworz pewn hierarchiczn struktur danych.
Z tego wzgldu klasa bazowa powinna mie te wszystkie elementy, z ktrych korzysta bd
klasy szczegowe. W strukturze polimorficznej klasa bazowa powinna dodatkowo zawiera
podstawowe wersje tych funkcji, ktre bd przykrywane w klasach pochodnych. Jeeli tylko
powysze zaoenia zostan spenione, bdziemy mogli posugiwa si pewnym spjnym interfejsem, zawierajcym wiele implementacji rnych obiektw. Dobr ilustracj tworzenia
i posugiwania si prost bibliotek klas bdzie przykad, w ktrym, na podstawie pewnej klasy bazowej umoliwiajcej przechowywanie dwu wymiarw pewnych figur geometrycznych
przy wykorzystaniu standardowej funkcji skadowej dane(), bdziemy w stanie skonstruowa
klasy pochodne umoliwiajce obliczanie pola prostokta (klasa TPochodna1) i trjkta (klasa
TPochodna2). Funkcja dane() jest funkcj standardow, gdy suy jedynie do przechowywania
podstawowych wymiarw odpowiednich figur geometrycznych, natomiast funkcja pokazPole()
powinna by kategorii virtual. Wynika to z faktu, i pola powierzchni rnych figur oblicza si
przy wykorzystaniu rnych wzorw. Na listingu 4.7 pokazano przykad implementacji biblioteki klas w C++Builderze.

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

247

248

C++Builder Borland Developer Studio 2006. Kompendium programisty

Listing 4.7. Kod gwnego moduu Unit_R4_07.cpp projektu Projekt_R4_07.bdsproj, wykorzystujcego


klasy polimorficzne konstruowane w stylu biblioteki klas VCL
#include
#include
#include
// Klasy

<vcl>
<sysutils.hpp>
<iostream>
polimorficzne w stylu VC/

using namespace std;


class TBazowa : public TObject
{
protected:
double a,b;
public:
void __fastcall dane(double x, double y)
{a = x; b = y;}
virtual void __fastcall pokazPole()
{cout << "Jestem klasa bazowa i nic nie obliczam ";
cout << "\n\n";}
};
//--------------------------------------------------------class TPochodna1 : public TBazowa
{
public:
virtual void __fastcall pokazPole()
{cout << "Jestem 1 klasa pochodna i obliczam" << endl;
cout << "pole prostokta = " << a*b << "\n\n";}
// a, b: dugo ci bokw prostokta
};
//--------------------------------------------------------class TPochodna2 : public TBazowa
{
public:
virtual void __fastcall pokazPole()
{cout << "Jestem 2 klasa pochodna i obliczam" << endl;
cout << "pole trjkta = " << 0.5*a*b << endl;}
// a: dugo podstawy trjkta, b: wysoko trjkta
};
//--------------------------------------------------------int main()
{
// utworzenie i zainicjowanie wskanikw do
// typu bazowego i klas pochodnych
TBazowa *ptrB = new TBazowa;
TPochodna1 *ptrP1 = new TPochodna1;
TPochodna2 *ptrP2 = new TPochodna2;
cout << endl << "Jawne wywoanie funkcji pokazPole()"
<< " klas TBazowa, TPochodna1 i TPochodna2" << "\n\n";
ptrB->pokazPole();
ptrP1->dane(2,2);
ptrP1->pokazPole();

248(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

249

ptrP2->dane(5,5);
ptrP2->pokazPole();
// wywoanie destruktorw klas
delete ptrB;
delete ptrP1;
delete ptrP2;
cout << endl;
system("P [SE");
return 0;

}
//---------------------------------------------------------

Analizujc powyszy program, natychmiast zauwaymy, i zainicjowanie kolejnych egzemplarzy klas wymaga utworzenia odpowiednich wskanikw oraz wykorzystania operatora new alokujcego je na stercie. Ze wzgldu na to, e typowi bazowemu oraz poszczeglnym typom
pochodnym zosta dynamicznie przydzielony pewien obszar pamici, ma sens mwienie o utworzeniu obiektw poszczeglnych klas, zwaszcza e interfejs (sposb wywoania elementw):
ptrP1->dane(2,2);
ptrP1->pokazPole();
ptrP2->dane(5,5);
ptrP2->pokazPole();

obu klas pochodnych jest taki sam pomimo pewnych rnic w wykonywanych przez nie obliczeniach.

Wskazwka
W dalszej czci ksiki pojcia obiekt bdziemy uywa w odniesieniu do elementw
programistycznych, do ktrych w trakcie dziaania programu zawsze mona wysa
komunikaty oznaczone stereotypami <<create>> i <<destroy>>, to znaczy wielokrotnie
wywoa ich konstruktor i destruktor. Oznacza to, i czasem ycia obiektw stworzonych
na bazie odpowiednich klas mona niemal dowolnie zarzdza.
Posugujc si funkcjami wirtualnymi w C++, naley zwrci baczn uwag na sposb inicjowania elementw klas. Dane takich typw, jak odwoania oraz zmienne, musz by zawsze we
waciwy sposb inicjowane. Jednak niezalenie od tego, w jaki sposb s inicjowane, bd dalej
pozostawa niezdefiniowane przed wywoywaniem konstruktora klasy bazowej. W C++Builderze
odpowiednie elementy biblioteki klas pisanych na wzr VCL s zawsze inicjowane wartoci
zero w momencie wywoywania ich konstruktorw (listing 4.8).
Listing 4.8. Kod gwnego moduu Unit_R4_08.cpp projektu Projekt_R4_08.bdsproj
#include <vcl>
#include <sysutils.hpp>
#pragma hdrstop
class TBazowa : public TObject
{
public:
__fastcall TBazowa() {init();}
virtual void __fastcall init() { }
};
//---------------------------------------------------------

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

249

250

C++Builder Borland Developer Studio 2006. Kompendium programisty


class TPochodna : public TBazowa
{
public:
TPochodna(int x) : zmienna(x) { }
virtual void __fastcall init()
{
// zmienna = 155;
if (zmienna == 0)
throw Exception("Inicjowanie warto ci 0");
}
private:
int zmienna;
};
//--------------------------------------------------------int main()
{
TPochodna *ptrP = new TPochodna(155);
delete ptrP;
system("P [SE");
return 0;
}
//---------------------------------------------------------

W podanym przykadzie wyjtek przechwytywany jest ostatecznie przez konstruktor klasy bazowej, tak jak pokazano to sekwencj rysunkw 4.2 4.5.

Rysunek 4.2. Prosty komunikat wyjtku

Rysunek 4.3. Miejsce generowania wyjtku


Poniewa klasa bazowa jest tworzona w pierwszej kolejnoci, zmienna zero nie moe w tym
momencie by zainicjowana jakkolwiek wartoci, gdy jest elementem typu pochodnego.
Jak widzimy, nawet jawne wpisanie wartoci do konstruktora klasy pochodnej nie przyniesie

250(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

251

Rysunek 4.4. Przetworzony wyjtek

Rysunek 4.5. Wyjtek przechwytywany przez konstruktor klasy bazowej


oczekiwanych efektw. Zawsze naley by wiadomym faktu, i nie mona inicjowa elementw skadowych klas pochodnych pisanych w stylu VCL, zanim nie zostanie wywoany konstruktor klasy bazowej.

Klas, ktra zawiera przynajmniej jeden element w postaci tzw. funkcji czysto wirtualnej (ang.
pure virtual function), nazywamy klas abstrakcyjn (ang. abstract class). W oglnej postaci
funkcj czysto wirtualn moemy zapisa nastpujco:
virtual typ __fastcall nazwa_funkcji(<lista_parametrw>) = 0;

Funkcje takie s zawsze deklarowane w klasie bazowej, jednak nigdy nie s definiowane wzgldem niej. Funkcja czysto wirtualna poczona z klas abstrakcyjn oznacza, e funkcja taka
nie ma swojej implementacji w macierzystej klasie. Funkcja czysto wirtualna zawsze powinna
zosta zaimplementowana w klasach pochodnych.
Jako przykad praktycznego wykorzystania klasy abstrakcyjnej rozpatrzmy sytuacj, w ktrej
klasa bazowa zawiera deklaracj funkcji pokazPole(), traktowanej jako funkcja czysto wirtualna.
Listing 4.9. Modu Unit_R4_09.cpp projektu Projekt_R4_09.bdsproj wykorzystujcego klas abstrakcyjn w stylu
biblioteki klas VCL
#include <vcl>
#include <sysutils.hpp>
#include <iostream>
using namespace std;
class TBazowa : public TObject
{

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

251

252

C++Builder Borland Developer Studio 2006. Kompendium programisty


protected:
double a,b;
public:
void __fastcall dane(double x, double y)
{a = x; b = y;}
// funkcja czysto wirtualna
virtual void __fastcall pokazPole() = 0;
};
//--------------------------------------------------------class TPochodna1 : public TBazowa
{
public:
virtual void __fastcall pokazPole()
{cout << "Jestem 1 klasa pochodna i obliczam" << endl;
cout << "pole prostokta = " << a*b << "\n\n";}
};
//--------------------------------------------------------class TPochodna2 : public TBazowa
{
public:
virtual void __fastcall pokazPole()
{cout << "Jestem 2 klasa pochodna i obliczam" << endl;
cout << "pole trjkta = " << 0.5*a*b << endl;}
};
//--------------------------------------------------------int main()
{
// utworzenie i zainicjowanie obiektw klas z wykorzystaniem
// konstruktorw domy lnych
TPochodna1 *ptrP1 = new TPochodna1;
TPochodna2 *ptrP2 = new TPochodna2;
cout << endl << "Jawne wywoania funkcji pokazPole()"
<< " klas TPochodna1 i TPochodna2" << "\n\n";
ptrP1->dane(2,2);
ptrP1->pokazPole();
ptrP2->dane(5,5);
ptrP2->pokazPole();
// wywoanie destruktorw klas i zniszczenie obiektw
delete ptrP1;
delete ptrP2;
cout << endl;
system("P [SE");
return 0;

}
//---------------------------------------------------------

Na rysunku 4.6 przedstawiono statyczny diagram klas dla przykad z listingu 4.9.

252(29-05-06/14:07)

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium programisty\

Rozdzia 4. G Wczesne oraz pne wizanie

253

Rysunek 4.6. Wymodelowanie przykadu 4.9 w postaci statycznego diagramu klas


Analizujc przykad 4.9, na pewno zauwaymy, i nie zosta utworzony i zainicjowany
wskanik do typu bazowego. Wynika to z faktu, e klasa TBazowa zawiera jedn funkcj czysto
wirtualn, co z kolei skutkuje niemonoci utworzenia jej obiektu. Jeeli w programie gwnym
nastpiaby prba jawnego utworzenia i zainicjowania obiektu na bazie klasy abstrakcyjnej:
TBazowa *ptrB = new TBazowa;

pojawiajcy si komunikat kompilatora:


[C++ Error] [nit1.cpp(35): E2352 Cannot create instance of abstract class 'TBazowa'

nie pozostawia nam cienia wtpliwoci, gdy nie mona skonstruowa obiektu na podstawie
klasy zawierajcej funkcj czysto wirtualn.

Wskazwka
Nie mona tworzy obiektw na bazie klas abstrakcyjnych. Klas takich uywamy
wycznie w charakterze klas bazowych dziedziczonych przez inne klasy pochodne.
Moliwe jest jednak tworzenie wskanikw nietraktowanych jako dynamiczne obiekty
w stylu jzyka C++ (tzw. wskanikw tradycyjnych) do tego typu klas, np.:
TBazowa *ptrB;

D:\Roboczy Jarek\makiety poprawki i druku pdf\C++Builder Borland Developer Studio 2006. Kompendium
programisty\04.doc (29-05-06/14:07)

253

You might also like