Listing 3.42 zawiera przykład, w którym sprawdzana jest wersja kompilatora i ewentualnie wyświetlana informacja o wykryciu C++Builder 2006. Można sobie jednak wyobrazić, że od wersji kompilatora zależy coś poważniejszego, np. dołą- czenie odpowiednich plików nagłówkowych. Listing 3.42. Treść komunikatu zależy od wersji kompilatora #if __BORLANDC__ >= 0x5=0 ShowMessage("WEkrEtE kompilator: C++Builder 2006 lub nowszE"); #else ShowMessage("Starsza wersja kompilatora"); #endif Należy zwrócić uwagę, że znaczenie dyrektyw z listingu 3.42, pomimo podobnego efektu, jest zupełnie inne niż konstrukcji C++ if..else. W przypadku dyrektywy #if wybór instrukcji, która ma być wykonana, dokonuje się już w momencie kompilacji, a zatem do skompilowanego pliku trafia tylko jedna opcja. 88 Część I ¨ Zintegrowane środowisko programistyczne i język programowania C++ Stałe preprocesora Stała __BORLANDC__ zdefiniowana została w bibliotekach kompilatora bcc32 za pomocą dyrektywy #define, zapewne w następujący sposób: #define __BORLANDC__ 0x5=0 Oczywiście ta stała pojawia się tylko w kompilatorze C++ firmy Borland. Jeżeli przy-gotowujemy kod, który może być kompilowany w innych środowiskach, to musimy uwzględnić fakt, że ta stała w ogóle nie jest zdefiniowana11. Służą do tego dyrektywy #ifdef i #ifndef. Pierwsza reaguje na obecność stałej, druga na jej brak. Oto przykład: Listing 3.43. A co, gdy stała w ogóle nie jest zdefiniowana? #ifdef __BORLANDC__ #if __BORLANDC__ >= 0x5=0 ShowMessage("WEkrEtE kompilator: C++Builder 2006 lub nowszE"); #else ShowMessage("Starsza wersja kompilatora"); #endif #else ShowMessage("Nie wEkrEto kompilatora firmE Borland"); #endif Ze względu na możliwości optymalizacji kodu przez kompilator i możliwość wystą- pienia trudnych do wytropienia błędów, nie należy dyrektywy #define używać do definiowania typów, np. #define pdouble double* (zamiast tego należy użyć instrukcji C++ tEpedef np. tEpedef double* pdouble;), oraz do definiowania stałych (do tego należy używać zmiennych z modyfikatorem const). Bardzo ważnym zastosowaniem dyrektyw #define i #ifndef jest ochrona plików na-główkowych przed wielokrotnym włączaniem za pomocą dyrektywy #include. Zagadnienie to zostanie omówione szczegółowo w rozdziale 5. Makra Dyrektywa #define może być użyta z argumentem, co pozwala na definiowanie tzw. makr, np.: #define _kwadrat(arg) (arg*arg) Makra są jednak bardzo silnym narzędziem i przez to zbyt niebezpiecznym. W momencie kompilacji „ciało” makra jest wstawiane w każde miejsce wystąpienia jego nazwy — to może czasem prowadzić do zupełnie zaskakujących rezultatów. 11 Wszystkie kompilatory pozwalają na identyfikację za pomocą stałych preprocesora np. _MSC_VER (Visual C++), __GNUC__ (g++), _CRAYC (Cray CC), __SUNPRO_CC (Sun CC) itd. Rozdział 3. ¨ Typy zmiennych i instrukcje sterujące 89 Makra i stałe preprocesora (także generalnie nazywane makrami) mogą być również usunięte i w konsekwencji niewidoczne dla dalszej części kodu. Służy do tego dy-rektywa #undef. Zadania Usilnie namawiam, aby Czytelnik, zanim przejdzie do kolejnych rozdziałów, poświę- cił trochę czasu na powtórzenie przedstawionych w tym rozdziale podstaw C++. Doskonałą okazją do tego są poniższe zadania. Zdegenerowane równanie kwadratowe Jeżeli współczynnik a w równaniu kwadratowym równy jest 0, to równanie to staje się zwykłym równaniem liniowym bx + c = 0. Proponuję, aby Czytelnik uwzględnił taką sytuację w metodzie rozwiązującej równanie kwadratowe. Z kolei jeżeli jednocześnie a i b są równe zero, a c jest różne od zera, to należy zgłosić wyjątek informujący, że równanie jest sprzeczne. Silnia Przygotuj metodę, która, korzystając z pętli for, będzie obliczała silnię podanej liczby (użytkownik powinien móc wskazać tę liczbę za pomocą pola edycyjnego). Co to jest silnia liczby n? To funkcja, która jest iloczynem liczb (naturalnych) od 1 do n, a więc 1·2·3·4· ·5·…·n. Zwykle silnie zapisuje się, stosując wykrzyknik n!. Dla przykładu: 1! = 1, 3! = 6 itd. Gdy już sobie poradzimy z silnią, to przygotujmy drugą funkcję, która będzie obliczała funkcję n!!. Jest to odmiana silni, w której mnoży się co drugą liczbę, a więc 6!! = 6 · 4 · 2, 5!! = 5 · 3 · 1, itd. Pętle Skonstruuj takie pętle while i do...while, które będą odpowiadały dokładnie pętli for(int i=0;i<10;i++).... Korzystając z wybranej przez siebie pętli, znajdź największą liczbę, przez którą można bez reszty podzielić dwie wskazane w polach edycyjnych liczby naturalne typu bRte. Ikony formy Zbiór ikon widocznych z prawej strony paska tytułu formy określany jest za pomocą zbioru Form1->BorderIcons. Należy usunąć z niego ikony minimalizacji i maksymalizacji. Wykorzystaj do tego metodę zdarzeniową związaną ze zdarzeniem OnFormCreate formy. 90
|