[ Pobierz całość w formacie PDF ]
umożliwić określenie, że dany symbol jest typem szablonu klasy. Demonstruje to po-
niższy przykład:
W powyższym przypadku słowo kluczowe zostało zastosowane w celu okre-
ślenia, że jest typem zdefiniowanym w klasie . W ten sposób został zade-
klarowany jako wskaznik do typu .
Gdyby pominąć słowo kluczowe , kompilator przyjąłby, że symbol re-
prezentuje statyczną wartość (zmienną lub obiekt) klasy . Wtedy wyrażenie:
zostałoby zinterpretowane jako operacja mnożenia tej wartości przez wartość .
Typowym przykładem zastosowania słowa kluczowego jest szablon funkcji,
która używa iteratorów w celu dostpu do elementów kontenera STL (patrz podrozdział
3.5.4):
Rozdział 7. Szablony 417
Parametrem powyższego szablonu funkcji może być kontener STL typu . Szablon
funkcji wyświetla elementy tego kontenera, posługując si lokalnym iteratorem. Dla ite-
ratora tego określony został pomocniczy typ zdefiniowany przez kontener. Jego dekla-
racja wymaga użycia słowa kluczowego :
n
Składowe klas mogą być także szablonami. Dotyczy to tak wewntrznych klas pomoc-
niczych, jak i funkcji składowych.
Zastosowanie tej możliwości wyjaśnimy na przykładzie klasy . Stosy mogą być
sobie przypisywane tylko wtedy, gdy posiadają elementy takiego samego typu. Przypi-
sywanie stosów o różnych typach elementów nie jest możliwe, ponieważ domyślny
operator przypisania wymaga, by oba jego argumenty były tego samego typu.
Możliwość przypisywania stosów o różnych typach elementów możemy uzyskać poprzez
zdefiniowanie operatora przypisania za pomocą szablonu. Deklaracja klasy
wyglądać bdzie wtedy nastpująco:
418 C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
W deklaracji klasy zaszły nastpujące zmiany:
Pojawiła si deklaracja operatora przypisania stosu o innym typie elementów .
Szablon wykorzystuje kolejk ze wzgldu na sposób implementacji operatora
przypisania.
Operator przypisania stosu o elementach innego typu został zdefiniowany w nastpujący
sposób:
Przyjrzyjmy si najpierw składni definicji szablonu funkcji należącej do szablonu klasy.
Szablon o parametrze został zdefiniowany wewnątrz szablonu o parametrze :
Mogłoby si wydawać, że implementacja takiej funkcji bdzie polegać na bezpośrednim
dostpie do elementów stosu i skopiowaniu ich. Jednak zauważmy, że instancje sza-
blonów utworzone dla różnych typów same są różnymi typami. Dlatego też
posiada inny typ niż stos, dla którego wywoływany jest operator. Dostp do elementów
stosu możliwy jest jedynie za pośrednictwem publicznego interfejsu. W tym celu
musi nam wystarczyć funkcja . Jednak, aby kolejne elementy kopiowanego stosu
mogły pojawić si na jego szczycie, konieczne jest także użycie funkcji usuwają-
cej elementy stosu. Dlatego najpierw należy utworzyć kopi stosu . Ponieważ funk-
cja zwraca elementy stosu w odwrotnej kolejności do porządku, w jakim zostały
na nim umieszczone, zmuszeni jesteśmy użyć kontenera, który umożliwia wstawianie
elementów na początek. Skorzystamy w tym celu z kolejki dysponującej funkcją
.
Rozdział 7. Szablony 419
Zauważmy również, że funkcja operatora zachowuje kontrol typów. Stosy nie mogą
być przypisywane, gdy nie jest możliwe przypisanie ich elementów. Jeśli spróbujemy
przypisać stos wartości całkowitych stosowi łańcuchów, w poniższym wierszu pojawi
si błąd:
ponieważ funkcja zwraca łańcuch, który nie może zostać użyty jako typ .
Zwróćmy uwag, że szablon operatora przypisania nie ukrywa domyślnego operatora
przypisania. Operator ten jest nadal dostpny i wywoływany dla operacji przypisania
dwóch stosów tego samego typu.
Implementacj szablonu stosu możemy zmodyfikować tak, by wykorzystywała wektor.
Deklaracja szablonu stosu bdzie wyglądać nastpująco:
Ponieważ kompilator tworzy kod jedynie dla tych funkcji, które są rzeczywiście uży-
wane, możemy utworzyć stos wykorzystujący wektor do przechowywania elementów:
Dopóty, dopóki nie próbujemy przypisać stosowi drugiego stosu o innym typie ele-
mentów, program bdzie działać poprawnie.
Kompletny kod tego przykładu znajduje si w plikach tmpl/stack6.hpp i tmpl/stest6.cpp.
Nie należy si zrażać, jeśli kompilator zgłosi dla nich błdy. Ponieważ przykłady te wy-
korzystują praktycznie wszystkie najważniejsze konstrukcj jzyka C++ związane
z szablonami, niektóre niestandardowe kompilatory nie potrafią ich poprawnie skom-
pilować.
420 C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
n u n
Polimorfizm implementowany jest zwykle za pomocą dziedziczenia (patrz podrozdział
5.3). Możliwa jest również implementacja polimorfizmu za pomocą szablonów. Zostanie
ona przedstawiona w niniejszym podrozdziale.
n n
W przypadku zastosowania dziedziczenia do implementacji polimorfizmu klasa bazowa
(zwykle abstrakcyjna) definiuje interfejs uogólnienia, który używany jest przez szereg
klas konkretnych (patrz podr5ozdział 5.3).
Na przykład uogólnieniem obiektów geometrycznych może być klasa (wprowa-
dzona w podrozdziale 5.3.3), dla której tworzone są konkretne klasy pochodne (patrz
rysunek 7.1).
un
Polimorfizm
dynamiczny
zaimplementowany
z użyciem
dziedziczenia
Program wykorzystujący uogólnienie musi używać wskazników do obiektów klasy ba-
zowej, co może wyglądać nastpująco:
Rozdział 7. Szablony 421
Funkcje zostają skompilowane dla typu . Decyzja o tym, która funkcja
wywołana zostanie wewnątrz funkcji , zależy jednak od typu przekazanego
obiektu i podejmowana jest w czasie wykonania programu. Jeśli funkcji zostanie
przekazany obiekt klasy , to wywołana zostanie funkcja . Jeśli
obiekt reprezentujący odcinek, to funkcja . Podobnie wewnątrz funkcji
podejmowana jest decyzja, którą funkcj należy wywołać dla da-
nego obiektu geometrycznego. Zastosowanie wskazników obiektów typu umożli-
[ Pobierz całość w formacie PDF ]