Zanim przejdę do konkretnego przykładu, który nie jakoby przyobiecałem muszę opisać pokrótce sposób tworzenia szablonów klas. Wcześniej już omawiane były szablony funkcji na stronie Programowanie → Podstawy C++ → Szablony funkcji a więc słowa kluczowe template oraz typename powinny być Ci już znane. Oto prosty przykład deklaracji szablonu klasy:
#include <iostream>
template <typename typ1, class typ2> class A // tutaj zadeklarowałem użycie dwóch typów danych
{
private:
typ1 t1; // tutaj będzie deklarowana zmienna typu typ1
public:
typ2 t2; // a tu obiekt klasy typu typ2
// To jest konstruktor szablonu klasy A
A(typ1 t1, typ2 &t2):t1(t1),
t2(t2)
{};
inline typ1 GetT1(){return t1;}; // to jest metoda zwracająca wartość pola t1
void SetT1(typ1 t1){this->t1 = t1;}; // to jest metoda ustawiająca wartość pola t1
};
class B // przykładowa klasa testowa
{
private:
int value;
int value2;
public:
B():value(0),value2(0){}; // prosty domyślny konstruktor
};
int main(){
B b;
A<int, B>(10,b); // tworzenie konkretnego obiektu według szablonu klasy A
cout<<"Wcisnij enter, aby zamknac program...";
cin.get();
return 0;
}
Tworzenie własnej klasy kolejki LIFO
LIFO (skrót od last in first out - ostatni wchodzi pierwszy wychodzi) to sposób przechowywania danych w taki sposób, że ostatni element danych zawiera wskaźnik do wcześniej dodanych elementów. Efektem tego, aby zdjąć i-ty element stosu trzeba najpierw zdjąć wszystkie jego nadrzędne elementy. Sytuację tą często porównuje się do stosu książek, aby spod takiego stosu wyjąć jakąś książkę, trzeba najpierw zdjąć te leżące nad.
Oto przykład szablonu klasy stack oraz dodatkowo definicji klasy typy point2d:
#include <iostream>
using namespace std;
template <typename type> class stack{
private:
type value; // element zawarty w stosie
stack* st; // wskaźnik do wcześniej dodanych elementów stosu
public:
stack(type value):st(NULL),value(value){}; // konstruktor tworzący pierwszy element stosu
stack(type value,stack* st):st(st),value(value){}; // konstruktor tworzący kolejny element stosu
void Add(stack** pts, type value){stack* s = new stack(value,this);*pts = s;}; // dodawanie elementu stosu
void RemoveStack(stack** pts){stack* st2 = st; st = NULL, delete this; *pts = st2;}; // usuwanie elementu stosu
~stack(){if(st){delete st; st=NULL;}cout<<"Pointer stack is deleted"<<endl;}; // zwalnianie pamięci stosu
void WriteAllStack(){value.Write();if(st){st->WriteAllStack();}}; // wypisywanie elementów stosu
int Size(){int s = 1; stack* st2 = st;while(st2){s++; st2 = st2->st;}return s;}; // pobieranie liczby elementów stosu
};
class point2d{
protected:
double x; // współrzędna x
double y; // współrzędna y
public:
point2d():x(0),y(0){}; // Konstruktor ustawiajacy domyślne współrzędne
point2d(point2d &p):x(p.x),y(p.y){}; // Konstruktor kopiujący
point2d(double x,double y):x(x),y(y){}; // Konstruktor ustawiający podanymi liczbami
void operator = (point2d &p){x = p.x; y = p.y;}; // Operator podstawiający
void operator *=(double k){x *= k; y *= k;};
void Write(){std::cout<<"x="<<x<<"; y="<<y<<"n";}; // Wypisywanie współrzędnych punktu na ekranie
inline double GetX() const {return x;}; // Pobieranie wartości współrzędnej x
inline double GetY() const {return y;}; // Pobieranie wartości współrzędnej y
void SetX(double x){this->x=x;}; // Ustawianie wartości współrzędnej x
void SetY(double y){this->y=y;}; // Ustawianie wartości współrzędnej y
~point2d(){}; // Destruktor
};
W powyższym kodzie znalazła się taka oto metoda szablonu klasy A:
void WriteAllStack(){value.Write();if(st){st->WriteAllStack();}}; // wypisywanie elementów stosu
Warto się jej przyjrzeć, ponieważ w ta metoda wywołuje metodę wewnętrzną obiektu pola klasy value.Write(), a to z kolei oznacza, że do stosu mogą być dodawane jedynie takie obiekty klas, które w swej definicji mają zadeklarowaną funkcję Write().
Poniżej zamieszczam przykładowy kod pokazujący operacje na stosie:
int main(){
// Dodawanie elementów stosu
point2d p(0,0);
sPoints = new stack<point2d>(p); // tworzenie pierwszego elementu stosu zawierającego obiekt klasy typu point2d
for(int i = 0; i < 10; i++){
point2d p(i,i);
sPoints->Add(&sPoints, p); // dodawanie nowego elementu stosu
}
cout<<endl<<"Wypisywanie elementow stosu:"<<endl<<endl;
sPoints->WriteAllStack(); // wypisuję elementy stosu
cout<<endl<<"Usuwanie elementu stosu:"<<endl<<endl;
sPoints->RemoveStack(&sPoints); // usuwa ostani element stosu
cout<<endl<<"Wypisywanie elementow stosu:"<<endl<<endl;
sPoints->WriteAllStack(); // wypisuję elementy stosu
cout<<endl<<"Usuwanie elementu stosu:"<<endl<<endl;
sPoints->RemoveStack(&sPoints);
cout<<endl<<"Wypisywanie elementow stosu:"<<endl<<endl;
sPoints->WriteAllStack();
cout<<endl<<"Liczba elementow stosu: "<<sPoints->Size()<<endl; // tutaj metoda Size() określa ile elementów znajduje się w stosie
cout<<endl<<"Zwalnianie pamieci stosu:"<<endl<<endl;
if(sPoints){ // jeżeli sPoinr ma przypisaną pamięc to
delete sPoints; // zwolnij pamięć
sPoints = NULL; // i przypisz zero
}
cout<<endl;
cout<<"Wcisnij enter, aby zamknac program...";
cin.get();
return 0;
}