2. Szablony klas

2.1. Typy uogólnione

Sztandarowym przykładem typów uogólnionych są różnego rodzaju kontenery (pojemniki), czyli obiekty służące do przechowywania innych obiektów. Jest oczywiste, że kod kontenera jest w dużej mierze niezależny od typu obiektów w nim przechowywanych. Jako przykład weźmy sobie stos liczb całkowitych. Możliwa definicja klasy stos może wyglądać następująco, choć nie polecam jej jako wzoru do naśladowania w prawdziwych aplikacjach:


class Stos {
private:
    int m_elementy[N];
    size_t m_szczyt;
public:
    static const size_t N=100;
    Stos():m_szczyt(0) {};
    void wstaw(int val) {m_elementy[m_szczyt++]=val;}
    int zdejm() {return m_elementy[--m_szczyt];}
    bool czyPusty() {return (m_szczyt==0);}
};

Ewidentnie ten kod będzie identyczny dla stosu obiektów dowolnego innego typu, pod warunkiem, że typ ten posiada zdefiniowany operator=() i konstruktor kopiujący.

W celu zaimplementowania kontenerów bez pomocy szablonów możemy próbować podobnych sztuczek jak te opisane w poprzednim rozdziale. W językach takich jak Java czy Smalltalk, które posiadają uniwersalną klasę Object, z której są dziedziczone wszystkie inne klasy, a nie posiadają (Java już posiada) szablonów, uniwersalne kontenery są implementowane właśnie poprzez rzutowanie na ten ogólny typ. W przypadku C++ nawet to rozwiązanie nie jest praktyczne, bo C++ nie posiada pojedynczej hierarchii klas.