27, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta


Rozdział 27.
Programowanie w C++


Rick McMullin

W tym rozdziale:

Język C++

C++ to wersja języka C rozszerzona o obsługę obiektów. Język ten opracowany został w Bell Labs na początku lat osiemdziesiątych i szybko zyskał sobie uznanie i popularność wśród programistów. Na rynku istnieje obecnie kilkanaście różnych kompilatorów tego języka. Najpopularniejsze z kompilatorów przeznaczonych dla platformy PC to Borland C++, Microsoft Visual C++, Zortech C++ i Watcom C++. Przeznaczone są one do tworzenia programów działających w systemach DOS i Windows, choć niektóre z nich potrafią również tworzyć programy pracujące pod kontrolą Windows NT i OS/2. Oczywiście istnieje również wiele kompilatorów języka C++ przeznaczonych dla innych platform sprzętowych.

W przypadku większości systemów UNIX-owych kompilatory języka C++ rozprowadzane są przez dystrybutorów systemu. Podobnie jest w przypadku Linuxa. Kompilator C++, który kiedyś nazywał się g++, jest bardzo blisko spokrewniony z GCC. W wersji 2.0 oba te kompilatory zostały scalone w jeden program.

Obecnie GCC to połączenie kompilatorów języków C, C++ oraz C z obiektami. W systemie nadal znajduje się plik o nazwie g++, ale jest on tylko skryptem wywołującym kompilator GCC z odpowiednimi opcjami.

Dlaczego C++?

C++ i programowanie obiektowe (ang. object-oriented programming, OOP) nie powstały od razu. Wiele lat temu, gdy na świecie panowały komputery ośmiobitowe, programiści zamiast języka maszynowego zaczęli używać asemblera, wykorzystując nieco większe możliwości obliczeniowe następców komputerów czterobitowych. Umożliwiło to przerzucenie części pracy związanej z tworzeniem programu na komputer.

Z upływem czasu moc obliczeniowa komputerów rosła i możliwe stało się pisanie coraz bardziej skomplikowanych programów. Było to jednak coraz trudniejsze. Powstawać zaczęły kompilatory języków wyższego poziomu, które brały ogrom „czarnej roboty” na siebie. Pierwsze języki były językami strukturalnymi - na przykład FORTRAN, COBOL, Pascal czy C. Strukturalizacja programów pozwalała na ich uproszczenie, zwiększenie przejrzystości, a przede wszystkim zmniejszenie liczby błędów dzięki podzieleniu zadania na mniejsze problemy (funkcje i procedury), łatwiejsze do rozwiązania.

Programowanie strukturalne dobrze spełniało swoją funkcję, ale znów tylko do pewnego czasu. W miarę wzrostu rozmiarów aplikacji zaczęło zawodzić. Programowanie zorientowane obiektowo powstało jako odpowiedź na problemy stwarzane przez programowanie strukturalne.

Główne nowe pojęcia wprowadzane przez OOP to:

Hermetyzacja danych

Przy programowaniu strukturalnym problemy pojawiały się najczęściej wtedy, gdy różne funkcje czy moduły programu korzystały ze wspólnych danych. Dowolny fragment programu mógł odwoływać się do danych bez poinformowania o tym innego fragmentu.

Hermetyzacja danych ma na celu zabezpieczenie przed tego typu problemami. Polega ona na zgrupowaniu wspólnych danych, zapisaniu ich w odpowiednim typie i zapewnieniu spójnego interfejsu dostępu do nich. Dzięki temu nikt nie może skorzystać z danych, pomijając ten interfejs.

Najważniejszą zaletą takiego rozwiązania jest zabezpieczenie danych przed ich nieautoryzowaną bezpośrednią modyfikacją. Często bowiem zmiana danych musi wiązać się z jakimiś ściśle określonymi czynnościami. Poza tym zmiana struktury danych nie jest widziana na zewnątrz samej struktury, o ile tylko interfejs dostępu do danych pozostanie niezmieniony. Znacząco upraszcza to tworzenie i poprawianie bardziej złożonych programów.

W języku C++ hermetyzację danych zapewnia mechanizm klas.

Dziedziczenie

Dziedziczenie pozwala na ponowne użycie części kodu. Zwykle stosowane jest w przypadku, gdy jakaś część programu posiada zasadniczo wszystkie cechy posiadane przez inną część, plus kilka innych, na przykład gdy jeden obiekt jest szczególnym przypadkiem drugiego.

Dziedziczenie jest w języku C++ zaimplementowane jako dziedziczenie klas.

Polimorfizm

Polimorfizm umożliwia zdefiniowanie funkcji wykonujących różne działania w zależności od typu danych, na których operują. Moc tego mechanizmu ujawnia się, gdy informacje przesyłane są poprzez klasę bazową do klas pochodnych, i dla każdej z nich mogą one oznaczać coś innego.

Polimorfizm w języku C++ zaimplementowany jest poprzez funkcje wirtualne.

Klasy i metody

Klasy w języku C++ można w zasadzie wyobrażać sobie podobnie jak struktury w języku C, z tym, że oprócz danych mogą one zawierać również funkcje, które na tych danych mogą być wykonywane. Rozpatrzmy na przykład typ danych reprezentujący bryłę geometryczną. Bryły mogą mieć najróżniejsze kształty, ale wszystkie mają kilka wspólnych atrybutów, na przykład pole powierzchni czy objętość. Można zatem zdefiniować w języku C strukturę o nazwie bryla:

struct bryla {
float pole;
float obj;
}

Jeśli do tej definicji dołączymy jeszcze kilka funkcji, otrzymamy odpowiednik klasy:

struct bryla {
float pole;
float obj;

float licz_pole();

float licz_obj();
};

W ten sposób zadeklarowaliśmy klasę w języku C++. Funkcje wchodzące w skład klasy nazywa się metodami. Zmienną typu bryla nazywa się obiektem. Można ją zadeklarować w następujący sposób:

bryla kula1;

Obiekt jest fizyczną realizacją klasy, podobnie jak zmienna była realizacją typu.

Opcje kompilatora GCC

W tym podrozdziale opiszemy najczęściej używane opcje kompilatora GCC. Najpierw przyjrzymy się opcjom wspólnym dla języków C i C++, a następnie przejdziemy do omówienia opcji specyficznych tylko dla języka C++. Każda opcja dostępna dla języka C może być użyta dla języka C++ (choć nie zawsze ma to sens - w takim przypadku zostanie ona zignorowana).

0x01 graphic

Do kompilowania programów napisanych w języku C++ najłatwiej użyć skryptu g++, ponieważ ustawia on automatycznie wszystkie wymagane opcje.

Do kompilatora GCC przekazać można bardzo dużo różnego rodzaju opcji. Większość z nich uzależniona jest od konkretnej platformy sprzętowej albo służy do dokładnego „dostrajania” wygenerowanego kodu i prawdopodobnie nigdy nie będziesz musiał ich użyć. Poniżej omówimy opcje, które przydadzą Ci się w codziennej pracy.

Wiele opcji programu GCC wymaga podania więcej niż jednej litery. Z tego powodu nie jest możliwe grupowanie ich po wspólnym myślniku, jak ma to miejsce w przypadku większości programów systemu Linux. Przed każdą opcją znaleźć się musi osobny myślnik.

Skompilowanie programu bez podania żadnych opcji powoduje utworzenie pliku wykonywalnego o nazwie a.out. Jeśli chcesz, aby program wynikowy miał inną nazwę, powinieneś użyć opcji -o, na przykład jeśli chcesz, aby program wygenerowany na podstawie kodu źródłowego zapisanego w pliku o nazwie licznik.C (rozszerzenie .C oznacza, że plik zawiera program w języku C++, w przeciwieństwie do rozszerzenia .c, oznaczającego kod w języku C) miał nazwę licznik, powinieneś wydać polecenie:

gcc -olicznik licznik.C

0x01 graphic

Po opcji -o w wierszu poleceń nie powinno być spacji! Nazwa pliku wykonywalnego musi pojawić się bezpośrednio po opcji -o.

Inne opcje pozwalają decydować, na jakim etapie proces kompilacji ma zostać zakończony. Opcja -c powoduje pominięcie konsolidacji (konwersji plików pośrednich na plik wykonywalny), tworząc tylko skompilowane pliki pośrednie (z rozszerzeniem .o). Jest ona szczególnie przydatna przy tworzeniu większych programów, ponieważ pozwala uniknąć wielokrotnego kompilowania plików, które nie zostały zmodyfikowane.

Opcja -S powoduje zatrzymanie kompilacji po wygenerowaniu plików asemblera (z rozszerzeniem .s). Opcja -E powoduje tylko wstępne przetworzenie plików źródłowych i wykonanie dyrektyw preprocesora, wyniki przesyłając do standardowego urządzenia wyjściowego.

Opcje współpracy z debugerem i programem profilującym

Program GCC posiada również kilka opcji umożliwiających współpracę z debugerem i programem profilującym. Najczęściej używane z nich to -gstabs+ oraz -pg.

Opcja -gstabs+ powoduje dołączenie do kodu programu wykonywalnego dodatkowych informacji dla debugera gdb, co znacznie ułatwia wyszukiwanie usterek w programach. Proces wyszukiwania błędów w programach napisanych w języku C++ omówiony jest dokładniej w podrozdziale „Wyszukiwanie błędów w programach C++” w dalszej części tego rozdziału.

Opcja -pg powoduje dołączenie kodu generującego informacje o ilości czasu poświęconego na wywołanie każdej z funkcji programu, które mogą być następnie przetworzone przez program gprof. Jeśli chcesz dowiedzieć się czegoś więcej o tym programie, zajrzyj do podrozdziału „gprof” w rozdziale 26. „Programowanie w języku C”.

Opcje specyficzne dla języka C++

Opcje pozwalające na modyfikację sposobu kompilacji programów w języku C++ zebrane zostały w tabeli 27.1.

Tabela 27.1. Opcje kompilacji specyficzne dla C++

Opcja

Znaczenie

-fall-virtual

Traktowanie wszystkich możliwych funkcji składowych jako wirtualnych (wszystkich prócz konstruktorów oraz przeciążonych operatorów new i delete)

-fdollars-in-identifiers

Zezwolenie na używanie znaku $ w identyfikatorach; opcja zabraniająca jego użycia: -fnodollars-in-identifiers

-felide-constructors

Pomijanie konstruktorów tam, gdzie to możliwe

-fenum-int-equiv

Zezwolenie na niejawną konwersję z typu wyliczeniowego do int

-fexternal-templates

Generowanie mniejszego kodu dla szablonów - kompilator generuje tylko jedną kopię żądanej funkcji tam, gdzie jest ona zdefiniowana

cd. na następnej stronie

Tabela 27.1. cd. Opcje kompilacji specyficzne dla C++

Opcja

Znaczenie

-fmemorize-lookups

Użycie technik heurystycznych dla przyspieszenia kompilacji; opcja ta jest domyślnie wyłączona, ale różnice są widoczne tylko przy określonym typie danych wejściowych

-fno-script-prototype

Traktowanie deklaracji funkcji bez argumentów w ten sam sposób, jak w języku C (czyli akceptowanie dowolnej liczby argumentów)

-fno-null-objects

Założenie, że obiekty, do których odnoszą się referencje, są zainicjalizowane

-fsave-memorized

To samo co -fmemorize-lookups

-fthis-is-variable

Zezwolenie na przypisanie do wskaźnika this

-nostdinc++

Pominięcie wyszukiwania plików nagłówkowych
w standardowych katalogach C++

-traditional

To samo co -fthis-is-variable

-fno-default-inline

Funkcje zdefiniowane w ciele klasy nie są traktowane jako inline

-wenum-clash

Generowanie ostrzeżeń przy konwersji pomiędzy typami wyliczeniowymi

-woverloaded-virtual

Generowanie ostrzeżeń, gdy klasa pochodna może być zdefiniowana błędnie przez zadeklarowanie funkcji
wirtualnych; funkcja wirtualna w klasie pochodnej musi być wirtualna również w klasie bazowej

-wtemplate-debugging

Generowanie ostrzeżeń w przypadku, gdy niemożliwe będzie użycie debugera z powodu stosowania szablonów

+eN

Kontrola sposobu, w jaki używane będą funkcje wirtualne

-gstabs+

Dodanie do kodu programu dodatkowych informacji,
zrozumiałych tylko dla debugera GNU; dzięki nim może on prawidłowo obsługiwać programy w języku C++

Wyszukiwanie błędów w aplikacjach C++

Możliwość wyszukiwania błędów powstających podczas pisania programu to bardzo ważna część procesu tworzenia aplikacji. Debuger opisany w rozdziale 26. może również zostać użyty dla programów napisanych w języku C++. W tym podrozdziale opisane są najważniejsze różnice pomiędzy wyszukiwaniem błędów w programach napisanych w językach C i C++.

Podstawowe polecenia debugera gdb, przedstawione już raz w rozdziale 26., dla wygody podane są również w tabeli 27.2.

Tabela 27.2. Podstawowe polecenia gdb

Polecenie

Opis

file

Ładuje plik wykonywalny, w którym można będzie szukać błędów.

kill

Kończy działanie aktualnie wykonywanego programu.

list

Wyświetla listę sekcji kodu źródłowego użytego do utworzenia
pliku wykonywalnego.

next

Przechodzi do kolejnego wiersza kodu w bieżącej funkcji, bez wchodzenia do funkcji podrzędnych.

step

Przechodzi do kolejnego wiersza kodu w bieżącej funkcji, wchodząc również do funkcji podrzędnych.

run

Powoduje wykonanie załadowanego programu.

quit

Kończy pracę debugera gdb.

watch

Pozwala na sprawdzenie wartości zmiennej po każdej jej zmianie.

break

Ustawia pułapkę w kodzie źródłowym. Pułapka powoduje wstrzymanie wykonywania programu po dojściu do zadanego punktu.

make

Pozwala na przekompilowanie programu bez konieczności wychodzenia z gdb.

shell

Umożliwia wykonanie polecenia powłoki.

Z punktu widzenia programisty, proces wyszukiwania usterek w programach napisanych w języku C++ jest bardziej złożony, niż w przypadku programów w języku C. Główną przyczyną takiego stanu rzeczy jest obsługa funkcji wirtualnych oraz wyjątków. Debuger gdb potrafi poradzić sobie z tymi mechanizmami.

Wyszukiwanie błędów
w funkcjach wirtualnych

Język C+ implementuje polimorfizm za pomocą funkcji wirtualnych. Dzięki nim istnieć może więcej niż jedna funkcja o określonej nazwie. Jedynym sposobem na ich rozróżnienie jest określenie typów argumentów, na których funkcje te operują. Określenie typów stanowi sygnaturę funkcji. Przykładowo, funkcja o prototypie

void func(int x, real f)

posiada sygnaturę int, real. Mechanizm funkcji wirtualnych stwarza pewien problem: jeśli na przykład zdefiniowano kilka funkcji o nazwie licz, jak ustawić pułapkę wywoływaną przy odwołaniu do jednej z tych funkcji? Przy wyszukiwaniu błędów w programach napisanych w języku C można było to zrobić przez podanie po poleceniu break nazwy funkcji, np.:

(gdb) break licz

Ta metoda nie działa w przypadku funkcji wirtualnych, ponieważ nie wiadomo, o którą funkcję licz chodzi. Debuger gdb potrafi poradzić sobie z takim problemem na kilka sposobów. Pierwszym z nich jest podanie całego nagłówka funkcji, na przykład tak:

(gdb) break 'licz (float)'

Teraz gdb ma już dość informacji, by wiedzieć, którą funkcję miałeś na myśli. Drugie rozwiązanie to wybranie interesującej nas funkcji z menu wyświetlanego przez gdb, jeśli ma on wątpliwości co do tego, o którą funkcję chodzi. Wybranie pierwszej pozycji menu powoduje anulowanie polecenia. Druga pozycja umożliwia ustawienie pułapki we wszystkich funkcjach o danej nazwie. Pozostałe pozycje odnoszą się kolejno do wszystkich funkcji o zadanej nazwie. Spójrzmy na przykład:

(gdb) break bryla::licz
[0] cancel
[1] all
[2] file: bryla.C line number: 153
[3] file: bryla.C line number: 207
[4] file: bryla.C line number: 247
>2 3
Breakpoint 1 at 0xb234: file: bryla.C line 153
Breakpoint 2 at 0xa435: file: bryla.C line 207
Multiple breakpoints were set
Use the "delete" command to delete unwanted breakpoints
(gdb)

Wyszukiwanie błędów
w funkcjach obsługi wyjątków

Wyjątki (ang. exceptions) to błędy występujące podczas działania programu. W C++ można tworzyć własne funkcje służące do ich obsługi. Przykładowo, jeśli pisałeś program w C i używałeś funkcji malloc do przydzielenia bloku pamięci, za każdym razem musiałeś sprawdzić zwracaną przez nią wartość, aby upewnić się, że wszystko przebiegło pomyślnie. Gdyby język C posiadał mechanizm obsługi wyjątków, wystarczyłoby napisać jedną funkcję obsługi wyjątku zgłaszanego przez funkcję malloc.

W gdb dodano dwa polecenia pozwalające na wyszukiwania błędów w funkcjach obsługi wyjątków: polecenie catch, które ustawia pułapkę w aktywnej funkcji obsługi wyjątku, oraz catch info, które wyświetla informacje o wszystkich funkcjach obsługi wyjątków. Składnia polecenia catch jest następująca:

catch wyjatki

gdzie wyjatki to lista wyjątków, które należy przechwycić.

Polecenia gdb specyficzne dla C++

Oprócz poleceń catch i catch info, do obsługi programów napisanych w języku C++ dodano również nowe opcje poleceń set i show. Zostały one zebrane w tabeli 27.3.

Tabela 27.3. Opcje poleceń set i show specyficzne dla języka C++

Polecenie

Opis

set print demangle

Wyświetlanie nazw funkcji tak, jak pojawiają się one w kodzie źródłowym, a nie tak, jak przekazywane są do asemblera

show print demangle

Wyświetlanie informacji o tym, czy opcja print demangle
jest aktywna

set demangle-style

Definicja trybu wyświetlania nazw; dostępne wartości: auto, gnu, lucid i arm

show demangle-style

Wyświetlanie informacji o aktualnym trybie wyświetlania nazw

set print object

Wyświetlanie aktualnego typu obiektu podczas wyświetlania wskaźnika do niego

show print object

Wyświetlanie informacji o tym, czy opcja print object jest aktywna

set print vtbl

Wyświetlanie tablicy funkcji wirtualnych

show print vtbl

Wyświetlanie informacji o tym, czy opcja print vtbl jest aktywna

Biblioteki klas GNU C++

Pakiet GNU C++ zawiera również całkiem pokaźną bibliotekę klas. Jest to zestaw dość uniwersalnych klas, które mogą zostać użyte w różnych programach. Przykładami mogą być klasy do obsługi baz danych, graficznego interfejsu użytkownika czy implementujące abstrakcyjne struktury danych.

Na rynku istnieją również inne biblioteki klas obsługujących graficzny interfejs użytkownika, np. Microsoft Foundation Classes czy Borland's Object Windows Library, ale przeznaczone są one tylko dla platformy Windows.

W tym podrozdziale opiszemy niektóre możliwości oferowane przez biblioteki klas GNU C++.

Strumienie

Biblioteka wejścia / wyjścia libio jest implementacją strumieni obsługujących urządzenia standardowego wejścia i wyjścia dla programów opartych na interfejsie tekstowym. Jest ona funkcjonalnie niemal identyczna z bibliotekami dołączanymi do innych kompilatorów. Jej główną częścią jest obsługa strumieni wejścia, wyjścia oraz błędów. Odpowiadają one strumieniom znanym z języka C i nazywają się odpowiednio cin, cout i cerr. Dane można do nich wysyłać za pomocą operatora <<, a odczytywać operatorem >>.

Poniższy program pokazuje, jak można wykorzystać bibliotekę wejścia / wyjścia.

#include <iostream.h>
int main ()
{
char name[10];
cout << "Podaj imie.\n";
cin >> name;
cout << "Witaj " << name << ", jak leci?\n";
}

Łańcuchy znaków

Klasa String zastępuje znane z języka C tablice znaków zakończone zerem. Daje programiście nowe możliwości, na przykład pozwala na używanie operatorów i funkcji. W tabeli 27.4 zebrano operatory zdefiniowane dla obiektów klasy String.

Tabela 27.4. Operatory zdefiniowane dla obiektów klasy String

Operator

Znaczenie

str1==str2

Zwraca logiczną prawdę, jeśli tekst reprezentowany przez obiekt str1 jest taki sam, jak reprezentowany przez str2

str1!=str2

Zwraca logiczną prawdę, jeśli tekst str1 jest różny od str2

str1<str2

Zwraca logiczną prawdę, jeśli tekst str1 jest mniejszy (alfabetycznie) od str2

str1<=str2

Zwraca logiczną prawdę, jeśli tekst str1 jest mniejszy lub równy str2

str1>str2

Zwraca logiczną prawdę, jeśli tekst str1 jest większy od str2

str1>=str2

Zwraca logiczną prawdę jeśli tekst str1 jest większy lub równy str2

compare(str1,str2)

Porównuje teksty str1 i str2 bez zwracania uwagi na wielkość liter

str3=str1+str2

Zapisuje rezultat połączenia tekstów str1 i str2 do str3

Dostępne są również inne funkcje, pozwalające na różnego typu porównania, sklejenia czy wyszukiwanie i wycinanie fragmentów tekstów.

Liczby przypadkowe

W skład biblioteki klas GNU C++ wchodzą również klasy pozwalające na generowanie różnego typu liczb przypadkowych. Są to klasy RNG oraz Random.

Analiza danych statystycznych

Biblioteka klas zawiera też dwie klasy służące do zbierania i przetwarzania danych statystycznych. Są to klasy SampleStatistic oraz SampleHistogram. Klasa SampleStatistic umożliwia zbieranie danych oraz obliczanie podstawowych parametrów takiego zbioru, np. wartości średniej, maksimum i minimum, wariancji, odchylenia standardowego itd.

Klasa SampleHistogram jest pochodną klasy SampleStatistic i służy do wyświetlania histogramów.

Listy

Biblioteka klas GNU C++ pozwala na użycie dwóch rodzajów list: jednokierunkowych (klasa SLList) i dwukierunkowych (DLList). Dla obu zaimplementowane są wszystkie podstawowe metody. Najważniejsze z nich zebrane są w tabeli 27.5.

Tabela 27.5. Metody klas obsługujących listy

Metoda

Opis

lista.empty()

Zwraca logiczną prawdę, jeśli lista nie zawiera żadnych elementów

lista.length()

Zwraca liczbę elementów listy

lista.prepend(a)

Umieszcza element a na początku listy

lista.append(a)

Umieszcza element a na końcu listy

lista.join(lista2)

Dołącza listę list2 do listy lista, usuwając listę lista2

a=lista.front()

Zwraca wskaźnik do pierwszego elementu listy

a=lista.rear()

Zwraca wskaźnik do ostatniego elementu listy

a=lista.remove_front()

Usuwa z listy pierwszy element, zwracając wskaźnik do niego

lista.del_front()

Usuwa i niszczy pierwszy element listy

lista.clear()

Usuwa całą zawartość listy

lista.ins_after(i,a)

Wstawia element a do listy po pozycji i

lista.del_after(i)

Usuwa element następny po pozycji i

Dodatkowe metody obsługiwane przez listę dwukierunkową zebrane są w tabeli 27.6.

Tabela 27.6. Dodatkowe metody klasy DLList

Metoda

Opis

a=list.remove_rear()

Usuwa z listy ostatni element, zwracając wskaźnik do niego

list.del_rear()

Usuwa i niszczy ostatni element listy

list.ins_before(i,a)

Wstawia element a przed i

list.del(i,dir)

Usuwa element na bieżącej pozycji, a następnie przesuwa się do przodu o jedną pozycję, jeśli dir jest wartością dodatnią, w przeciwnym przypadku - o jedną pozycję do tyłu

Klasy Plex

Obiekty klasy Plex zachowują się podobne jak tablice, ale mają znacznie większe możliwości. Oto niektóre z ich własności:

Zdefiniowane zostały cztery typy struktur Flex: FPlex, która może rozrastać się i kurczyć w zdefiniowanych wcześniej granicach, XPlex, mogąca zmieniać rozmiary bez żadnych ograniczeń, RPlex, podobna do XPlex, ale posiadająca nowe możliwości indeksowania oraz MPlex, która jest pochodną RPlex, pozwalającą na logiczne usuwanie i odzyskiwanie elementów.

Tabela 27.7 zawiera niektóre metody i operatory tych klas.

Tabela 27.7. Metody i operatory klas Plex

Metoda

Opis

Plex b(a)

Przypisuje kopię struktury a do b

b=a

Kopiuje Plex a do b

a.length()

Zwraca liczbę elementów struktury a

a.empty()

Zwraca logiczną prawdę, jeśli a posiada 0 elementów

a.full()

Zwraca logiczną prawdę, jeśli struktura a jest pełna

a.clear()

Usuwa wszystkie elementy struktury a

a.append(b)

Dołącza Plex b do górnej części a

a.prepend(b)

Dołącza Plex b do dolnej części a

a.fill(z)

Wstawia do struktury elementy równe z na wszystkich pozycjach

a.valid(i)

Zwraca logiczną prawdę, jeśli indeks i jest prawidłowy

a.low_element()

Zwraca wskaźnik do elementu o najniższej pozycji

a.high_element()

Zwraca wskaźnik do elementu o najwyższej pozycji

Klasy Plex są bardzo przydatne. W oparciu o nie opracowano wiele innych klas z biblioteki GNU C++, na przykład stosy, kolejki, listy itp.

Stosy

Klasa Stacks jest implementacją stosu (ang. LIFO, last in, first out). Dostępne są trzy odmiany tej struktury: VStack - stos o ustalonym rozmiarze, podawanym podczas inicjalizacji, oraz XPStack i SLStack - stosy o dynamicznie zmienianych rozmiarach, różniące się nieco szczegółami implementacji.

Tabela 27.8 zawiera metody wspólne dla tych klas.

Tabela 27.8. Metody i operatory klas Stacks

Metoda

Opis

Stack st

Konstruktor

Stack st(rozm)

Konstruktor stosu o rozmiarze rozm

st.empty()

Zwraca logiczną prawdę, jeśli stos jest pusty

st.full()

Zwraca logiczną prawdę, jeśli stos jest pełny

st.length()

Zwraca liczbę elementów przechowywanych na stosie

st.push(x)

Odkłada element x na stos

x=st.pop()

Zdejmuje element ze stosu i przypisuje go zmiennej x

st.top()

Zwraca wskaźnik do najwyżej położonego elementu na stosie

st.del_top(0

Usuwa ze stosu najwyżej położony element

st.clear()

Usuwa ze stosu wszystkie elementy

Kolejki

Kolejki (ang. FIFO, first in, first out) implementowane są za pomocą klas Queue. Dostępne są trzy odmiany tych struktur: VQueue - kolejka o ustalonym rozmiarze (podawanym podczas inicjalizacji), oraz XPQueue i SLQueue - kolejki o rozmiarze zmienianym dynamicznie (podanie rozmiaru nie jest wymagane). W tabeli 27.9 zebrano metody zaimplementowane w tych klasach.

Tabela 27.9. Metody i operatory klas Queue

Metoda

Opis

Queue q

Konstruktor

Queue q(rozm)

Konstruktor kolejki o rozmiarze rozm

q.empty()

Zwraca logiczną prawdę, jeśli kolejka jest pusta

q.full()

Zwraca logiczną prawdę, jeśli kolejka jest pełna

q.length()

Zwraca liczbę elementów przechowywanych w kolejce

q.enq(x)

Dopisuje element x do kolejki

cd. na następnej stronie

Tabela 27.9. cd. Metody i operatory klas Queue

Metoda

Opis

x=q.deq()

Pobiera element z kolejki i przypisuje go do zmiennej x

q.front()

Zwraca wskaźnik do pierwszego elementu w kolejce

q.del_front(0

Usuwa z kolejki pierwszy element

q.clear()

Usuwa z kolejki wszystkie elementy

Oprócz wymienionych wyżej typów kolejek, w skład biblioteki klas GNU C++ wchodzą również klasy obsługujące kolejki dwukierunkowe i priorytetowe. Kolejka dwukierunkowa zawiera dodatkowe operatory pozwalające na dostęp do elementu przechowywanego na jej końcu. Kolejka priorytetowa pozwala na szybki dostęp do najmniejszego elementu i posiada dodatkowe operatory służące do wyszukiwania elementów.

Zbiory

Klasy Set używane są do przechowywania zbiorów elementów. Jedynym ograniczeniem nałożonym na elementy jest fakt, że nie mogą się one powtarzać. Dostępnych jest kilka implementacji tej klasy, ale wszystkie one mają taki sam interfejs. Metody tych klas zebrano w tabeli 27.10.

Tabela 27.10. Metody i operatory klas Set

Metoda

Opis

Set s

Konstruktor

Set s(rozm)

Konstruktor zbioru o maksymalnym rozmiarze rozm

s.empty()

Zwraca logiczną prawdę, jeśli zbiór jest pusty

s.length()

Zwraca liczbę elementów zbioru

i=s.add(z)

Dodaje element z do zbioru s, zwracając numer indeksu

s.del(z)

Usuwa ze zbioru s element z

s.clear()

Usuwa wszystkie elementy ze zbioru s

s.contains(z)

Zwraca logiczną prawdę, jeśli element z należy do zbioru s

s.(i)

Zwraca wskaźnik do elementu o indeksie i

i=s.first()

Zwraca indeks pierwszego elementu zbioru

s.next(i)

Przypisuje zmiennej i indeks następnego elementu zbioru s

i=s.seek(z)

Przypisuje zmiennej i indeks elementu z, jeśli należy on do zbioru s,
w przeciwnym przypadku - zero

set1==set2

Zwraca logiczną prawdę, jeśli set1 zawiera te same elementy, co set2

set1!=set2

Zwraca logiczną prawdę, jeśli zbiór set1 nie zawiera tych samych elementów, co set2

Tabela 27.10. cd. Metody i operatory klas Set

Metoda

Opis

set1<=set2

Zwraca TRUE, jeśli zbiór set1 jest podzbiorem set2

set1|=set2

Dodaje elementy zbioru set2 do zbioru set1

set1-=set2

Usuwa ze zbioru set1 wszystkie elementy, które występują w zbiorze set2

set1&=set2

Usuwa ze zbioru set1 elementy, które nie występują w set2

Oprócz zbiorów dostępne są również inne klasy o podobnej funkcji - są to klasy bag (ang. torba). Struktury tego typu mogą, podobnie jak zbiory, zawierać elementy w dowolnym porządku, ale różnią się od zbiorów tym, że mogą również zawierać elementy powtarzające się. Nie obsługują w związku z tym operatorów ==, !=, |=, <=, -= i &=. Nowe metody implementowane w klasie bag zebrano w tabeli 27.11.

Tabela 27.11. Metody klasy bag nie występujące w klasie Set

Metoda

Opis

b.remove(z)

Usuwa wszystkie wystąpienia elementu z

b.nof(z)

Zwraca liczbę wystąpień elementu z

Poza opisanymi wyżej, biblioteka klas GNU C++ zawiera jeszcze wiele innych użytecznych klas. Oprócz biblioteki dostarczanej wraz z kompilatorem, dostępne są także inne, darmowe biblioteki, mogące również okazać się bardzo przydatne.

Podsumowanie

C++ oferuje programiście o wiele więcej niż język C. Najbardziej oczywistą przewagą jest możliwość programowania obiektowego oraz dostępność elastycznych bibliotek klas. W tym rozdziale przyjrzeliśmy się kompilatorowi i debugerowi, a także omówiliśmy pokrótce najczęściej używane klasy wchodzące w skład biblioteki GNU C++.

Jednym z problemów, na które narzekali programiści używający języka C++, był brak darmowych programów narzędziowych. Jak zauważyłeś, o wiele więcej jest programów użytkowych wspomagających programowanie w języku C. Z upływem czasu sytuacja jednak się odwraca. Rosnąca ilość użytkowników języka C++ powoduje powstawanie nowych programów narzędziowych oraz ewolucję już istniejących. Nie należy więc obawiać się „przesiadki” na C++.

Kompilator i programy narzędziowe dla języka C omówione są w rozdziale 26. „Programowanie w języku C”.

Perl, język nadający się świetnie do pisania krótkich i wydajnych programów, przedstawiony jest w rozdziale 28. „Perl”.

Kompilatory innych języków dla systemu Linux opisane są w rozdziale 30. „Inne kompilatory”.

460 Część V Linux dla programistów

460 E:\Moje dokumenty\HELION\Linux Unleashed\Indeks\27.DOC

E:\Moje dokumenty\HELION\Linux Unleashed\Indeks\27.DOC 459

Rozdzia³ 27. Programowanie w C++ 459



Wyszukiwarka

Podobne podstrony:
43, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
34, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
58, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
26, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
08, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
10, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
57, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
29, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
46, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
60, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
36, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
49, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
62, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
D, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
55, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
28, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
61, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
42, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
03, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta

więcej podobnych podstron