Objektum elvű alkalmazások fejlesztése Verem típus osztály-sablonja Készítette: Gregorics Tibor
Készítsünk olyan újra-felhasználható kódot, amellyel vermeket lehet létrehozni és használni. Egy verem-objektum reprezentációját az határozza meg, hogy adunk-e felső korlátot a verem méretére. Ha igen, akkor statikus (tömbös azaz aritmetikai), ha nem, akkor dinamikus (szétszórt azaz láncolt) ábrázolást alkalmazunk majd. A verem osztályának példányosításnál tetszőlegesen választhassuk meg a verem elemeinek típusát.
Absztrakt ábrázolások: Időbélyeges elemek halmaza: Elején változtatható sorozat: push pop (e 3, 5) (e 2, 2) (e 1, 0) empty top push e 3 e 2 e 1 pop top empty
Statikus reprezentáció Dinamikus reprezentáció 0 size-1 vect e 1 e 2 e 3 h e 3 e 2 e 1 nil top 2 1. Rögzített a lefoglalt memória mérete, ami sokszor vagy feleslegesen nagy vagy kevés. 2. Tömbnyi szabad memória kell. 3. Adatelemek (top illetve vect[top]) elérési ideje konstans. 1. Valódi mérethez igazodik a lefoglalt memória (de a címeket is tárolja) 2. Sok kisméretű memória szelet kell. 3. Adatelemek elérési ideje általában lineáris, de itt csak az első elem kell, tehát konstans.
Stack Stack<int> si1; Stack<int> si2(20); Stack<string> ss; Stack<Test*> st; si1.push(4); ss.push("alma"); st.push(new Kup(2.0, 4.5)); +push() : void +pop() : +top() : +empty() : bool verem maximális mérete statikus reprezentációhoz Stack<> osztály-sablon példányosításai ahol az elemi-típus paramétere main.cpp
template <typename > class Stack { Stack(int max = 0); ~Stack(); void push(const &e); pop(); top() const; bool empty() const; Stack +push() : void +pop() : +top() : +empty() : bool ; private: Hogyan írható le mindkét reprezentáció? stack.hpp
<<interface>> Stack Interfész : a tisztán absztrakt osztály +push() : void +pop() : +top() : +empty() : bool Sajnos a példányosításnál nem írhatunk Stack<int> v(20) vagy Stack<int> v -t. Helyettük az ArrayReprStack<int> v(20) illetve LinkedReprStack<int> v használható. ArrayStackRepr -vect : [] -top : int +ArrayReprStack() +push() : void +pop() : +top() : +empty() : bool LinkedStackRepr -head : Node* +LinkedReprStack() +push() : void +pop() : +top() : +empty() : bool
Stack - *repr <<interface>> StackRepr +Stack(int max=0) +push(): void +pop() : +top() : +empty() : bool if (max==0) repr = new LinkedStackRepr<>(); else repr = new ArrayStackRepr <>(max); +push() : void +pop() : +top() : +empty() : bool ArrayStackRepr Ez esetben használható a Stack<int> v(20) illetve a Stack<int> v LinkedStackRepr repr >push(e) return repr >pop() return repr >top() return repr >empty() -vect : [] -top : int +ArrayStackRepr() +push(): void +pop() : +top() : +empty() : bool -head : Node* +LinkedStackRepr() +push(): void +pop() : +top() : +empty() : bool
template <typename > class Stack { Stack(int max = 0){ if (max==0) _repr = new LinkedStackRepr <>(); else _repr = new ArrayStackRepr <>(max); void push(const &e) { _repr->push(e); pop() { return _repr->pop(); top() const { return _repr->top(); bool empty() const { return _repr->empty(); ; private: StackRepr<> *_repr; stack.hpp
<<interface>> StackRepr +push() : void +pop() : +top() : +empty() : bool enum StackExceptions {EMPTYSTACK, FULLSTACK; template <typename > class StackRepr { virtual void push(const &e) = 0 ; virtual pop() = 0 ; virtual top() const = 0 ; virtual bool empty() const = 0 ; virtual ~StackRepr(){; ; stackrepr.hpp
<<interface>> StackRepr +push() : void +pop() : +top() : template <typename > +empty() : bool class ArrayStackRepr : public StackRepr<> { ArrayStackRepr(int max){ try { _vect.resize(max); catch(std::bad_alloc o){throw FULLSTACK; -top _top=-1; void push(const &e); pop(); -vect top() const; bool empty() const; A vector is egy sablon private: std::vector<> _vect; int _top; ; ArrayStackRepr Array : int arraystackrepr.hpp
template <typename > void ArrayStackRepr<>::push(const & e){ if(_top+1==(int)_vect.size()) throw FULLSTACK; _vect[++_top] = e; template <typename > ArrayStackRepr<>::pop(){ if(_top==-1) throw EMPTYSTACK; --_top; template <typename > ArrayStackRepr<>::top() const{ if(_top==-1) throw EMPTYSTACK; return _vect[_top]; template <typename > bool ArrayStackRepr<>::empty() const { return _top==-1; arraystackrepr.hpp
<<interface>> StackRepr template <typename > class LinkedStackRepr : public StackRepr<>{ +push() : void +pop() : LinkedStackRepr(){ _head = NULL; +top() : LinkedStackRepr(const LinkedStackRepr&); +empty() : bool LinkedStackRepr& operator=(const LinkedStackRepr&); ~LinkedStackRepr(){ destroy(); void push(const &e); pop(); top() const; bool empty() const; private: struct Node{ val; Node *next; ; A Node is egy sablon: Node<> Node(const &e, Node *n):val(e), next(n){; ; Node *_head; void destroy(); void copy(const LinkedStackRepr&); LinkedStackRepr -destroy() : void -copy() : void - *head Node +val : + *next linkedstackrepr.hpp
template <typename > void LinkedStackRepr<>::push(const & e) { try{ _head = new Node(e,_head); catch(std::bad_alloc o) { throw FULLSTACK; template <typename > LinkedStackRepr<>::pop() { if(_head==null) throw EMPTYSTACK; Node *p = _head; _head = _head->next; e = p->val; delete p; return e; template <typename > LinkedStackRepr<>::top() const { if(_head==null) throw EMPTYSTACK; return _head->val; template <typename > bool LinkedStackRepr<>::empty() const { return _head==null; linkedstackrepr.hpp
template <typename > LinkedStackRepr<>:: LinkedStackRepr(const LinkedStackRepr& r) { copy(r); template <typename > LinkedStackRepr<>& LinkedStackRepr<>:: operator=(const LinkedStackRepr& r) { if(this==&r) return *this; destroy(); copy(r); return *this; linkedstackrepr.hpp
template <typename > void LinkedStackRepr<>::copy(const LinkedStackRepr& r){ if(r._head==null) _head = NULL; else { try{ _head = new Node(r._head->value,NULL); Node *q = _head; Node *p = r._head->next; while(p!=null){ q->next = new Node(p->value,NULL); q = q->next; p = p->next; catch(std::bad_alloc o){ destroy(); throw FULLSTACK; félig felépített lista lebontása template <typename > void LinkedStackRepr<>::destroy(){ while(_head!=null){ Node *p = _head; _head = _head->next; delete p; linkedstackrepr.hpp
main.cpp int main() { stack.hpp enum StackExceptions { ; template <typname > class Stack { ; stackrepr.hpp enum StackReprExceptions { ; template <typname > class StackRepr { ; linkedstackrepr.hpp template <typname > class LinkedStackRepr : public StackRepr { ; arraystackrepr.hpp template <typname > class ArrayStackRepr : public StackRepr { ;
int main() { Stack<int> s; // Stack<int> s(10); try{ int i; while( cin >> i ){ s.push(i); catch (StackExceptions e){ if (e == FULLSTACK) cout << " "; while(!s.empty()){ cout << s.pop() << endl; return 0; main.cpp
- *repr +Stack(int max=0)... Stack + createenumerator() : Enumerator* return repr->createenumerator() StackRepr... + createenumerator() <<interface>> Enumerator (first, next, end, current) LinkedStackRepr ArrayStackRepr LinkedStackEnum - p : Node* ArrayStackEnum - ind : int + createenumerator() + createenumerator() bejár bejár (first, next, end, current) * -*ref (first, next, end, current) * -*ref return new LinkedStackEnum(this) return new ArrayStackEnum(this)
template <typename > class Enumerator{ virtual ~Enumerator() {; virtual void first() = 0; virtual void next() = 0; virtual current() const = 0; virtual bool end() const = 0; ; enumerator.hpp
template <typename > class ArrayStackRepr : public StackRepr<>{... class ArrayStackEnumerator : public Enumerator<> { ArrayStackEnumerator(ArrayStackRepr *r){ _ref = r; void first() { _i = 0; void next() { ++_i; current() const { return _ref->_vect[_i]; bool end() const { return _i > _ref->_top; private: ArrayStackRepr *_ref; int _i; ; ; Enumerator<>* createenumerator() { return new ArrayStackEnumerator(this); arraystackrepr.hpp
template <typename > class LinkedStackRepr : public StackRepr<>{... class LinkedStackEnumerator : public Enumerator<> { LinkedStackEnumerator(LinkedStackRepr *r){ _ref = r; void first() { _p = _ref->_head; void next() { _p = _p->next; current() const { return _p->val; bool end() const { return _p == NULL; private: LinkedStackRepr *_ref; LinkedStackRepr::Node *_p; ; ; Enumerator<>* createenumerator() { return new LinkedStackEnumerator(this); linkedstackrepr.hpp
template <typename > class Stack; template <typename > std::ostream& operator<<(std::ostream& out, Stack<>& s); template <typename > class Stack { friend std::ostream& operator<< <> (std::ostream& out, Stack& s); template <typename > ; std::ostream& operator<< (std::ostream& out, Stack<>& s) { out << "["; Enumerator<> *t = s.createenumerator(); t->first(); if(! t->end()) out << " " << t->current(); for( t->next();!t->end(); t->next()) out << ", " << t->current(); out << " ]"; return out; stack.hpp
int main() { Stack<int> s; // Stack<int> s(10); try{ int i; while( cin >> i ){ s.push(i); catch (StackExceptions e){ if (e == FULLSTACK) cout << " "; cout << s << endl; return 0; main.cpp
template <typename = int> class Stack{ ; Stack<int> y; Stack<> y; Stack<Test*> y; template <typename, int maxsize = 100> class ArrayRepr{ ArrayRepr(int max = 0) { try{ vect.resize(maxsize); catch(std::bad_alloc o){ throw FULLSTACK; top=-1; ; Stack<int, 10> y; Stack<int> y;