Szablony klas na przykładzie własnej kolejki LIFO (stosu)
Stronę tą wyświetlono już: 958 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;
- }