Szablony klas na przykładzie własnej kolejki LIFO (stosu)

Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 4549 razy

Wstęp

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; }
Propozycje książek