Tervminták II. (Híd, Bejáró, Gyártófüggvény) Halmaz és bejárása Osztály-sablonok

Hasonló dokumentumok
Objektum elvű alkalmazások fejlesztése. Verem típus osztály-sablonja

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

mul : S T N 1 ha t S mul(s, t) := 0 egyébként Keresés Ezt az eljárást a publikus m veletek lenti megvalósításánál használjuk.

.AA Megoldó Alfréd AA.

503.AA Megoldo Arisztid 503.A

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

Objektum elvű alkalmazások fejlesztése Programozási tételek újrafelhasználása 1.

Programozás Minta programterv a 2. házi feladathoz 1.

Objektumelvű programozás

128. AA Megoldó Alfréd AA 128.

OAF Gregorics Tibor: Minta dokumentáció a 4. házi feladathoz 1. Feladat. Megoldás

Objektum elvű alkalmazások fejlesztése Programozási tételek újrafelhasználása 1. Készítette: Gregorics Tibor

3. Osztályok II. Programozás II

Pénzügyi algoritmusok

Programozás(A szakirány) II. beadandó feladat Farkas András HP6S15 1. csoport Veszprémi Anna / Hudoba Péter

Programozás II. 4. Dr. Iványi Péter

Programozás II gyakorlat. 8. Operátor túlterhelés

C++ programozási nyelv Konstruktorok-destruktorok

feladat pont min elért

Maximum kiválasztás tömbben

117. AA Megoldó Alfréd AA 117.

1.AA MEGOLDÓ BERCI AA 1.

A feladat lényege egy felhasználói típusnak a zsák típusnak a megvalósítása.

OAF Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1.

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok

500. CC Megoldó Alfréd CC 500.

Programozási tételek újrafelhasználása

A lista eleme. mutató rész. adat rész. Listaelem létrehozása. Node Deklarálás. Létrehozás. Az elemet nekünk kell bef zni a listába

500. AA Megoldó Alfréd AA 500.

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN

List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error

228. AA Default Konstruktor AA 228.

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék

STL. Algoritmus. Iterátor. Tároló. Elsődleges komponensek: Tárolók Algoritmusok Bejárók

500.AJ Megoldó Magyar Magdolna 500.J

Bánsághi Anna 2014 Bánsághi Anna 1 of 33

Programozási nyelvek Java

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek

Elemi Alkalmazások Fejlesztése II.

Felhasználó által definiált adattípus

Objektum elvű alkalmazások fejlesztése Kifejezés lengyel formára hozása és kiértékelése

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum

OOP: Java 8.Gy: Abstract osztályok, interfészek

Elemi alkalmazások fejlesztése II. 2. Beadandó feladat Juhász Ádám

1000.AA Megoldo Alfréd 1000.A

Bevezetés a programozásba 2

Fejlett programozási nyelvek C++ Iterátorok

és az instanceof operátor

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

Programozási technológia

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben?

Generikus Típusok, Kollekciók

1. Bevezetés A C++ nem objektumorientált újdonságai 3

Generikus osztályok, gyűjtemények és algoritmusok

C++ Standard Template Library (STL)

500. DD Megoldó Alfréd DD 500.

feladat pont min elért

500.AA Megoldó Kulcsár 500.A

ISA szimulátor objektum-orientált modell (C++)

Osztály és objektum fogalma

0. Megoldó Manó 0. Programozás alapjai 2. (inf.) pót zárthelyi gyak. hiányzás: 2 n/kzhp: n/11,5. ABCDEF IB.028/2.

1. Alapok. Programozás II

500.AA Megoldo Arisztid 500.A

infix kifejezés a+b ab+ +ab postfix kifejezés prefix kifejezés a+b ab+ +ab a+b ab+ +ab Készítette: Szabóné Nacsa Rozália

C++ programozási nyelv

Bevezetés a Programozásba II 8. előadás. Polimorfizmus Giachetta Roberto

A C++ Standard Template Library rövid összefoglalás

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés

Programozás alapjai II. (4. ea) C++

Programozás II gyakorlat. 6. Polimorfizmus

Programozás. C++ osztályok. Fodor Attila. Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék

JAVA PROGRAMOZÁS 2.ELŐADÁS

Bevezetés a programozásba Előadás: A const

Collections. Összetett adatstruktúrák

Számítógép és programozás 2

C# osztályok. Krizsán Zoltán

Objektumok inicializálása

OOP #14 (referencia-elv)

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

Osztályok. construct () destruct() $b=new Book(); $b=null; unset ($b); book.php: <?php class Book { private $isbn; public $title;

Széchenyi István Egyetem. Programozás III. Varjasi Norbert

Programozási tételek újrafelhasználható osztálysablon könyvtára

Programozás II. 2. Dr. Iványi Péter

Programozási nyelvek Java

Pénzügyi algoritmusok

OOP és UML Áttekintés

EAF II Feladat dokumentáció IV. feladat 4. házi feladathoz

Interfészek. PPT 2007/2008 tavasz.

Programozás II. ATM példa Dr. Iványi Péter

HORVÁTH ZSÓFIA 1. Beadandó feladat (HOZSAAI.ELTE) ápr 7. 8-as csoport

Programozás I. 3. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar

Alkalmazott modul: Programozás 4. előadás. Procedurális programozás: iteratív és rekurzív alprogramok. Alprogramok. Alprogramok.

Osztályok. 4. gyakorlat

C# nyelv alapjai. Krizsán Zoltán 1. Objektumorientált programozás C# alapokon tananyag. Általános Informatikai Tanszék Miskolci Egyetem

Programozás alapjai II. (7. ea) C++

Már megismert fogalmak áttekintése

Programozási nyelvek (ADA)

Informatikai Kar. 3. fejezet. alapismeretek. Giachetta Roberto

Virtuális függvények (late binding)

Szövegek C++ -ban, a string osztály

Átírás:

Tervminták II. (Híd, Bejáró, Gyártófüggvény) Halmaz és bejárása Osztály-sablonok

1.Feladat Készítsünk olyan kódot, amely segítségével természetes számokat tároló halmazok hozhatók létre. o Egy halmaz-objektum reprezentációja attól függjön, hogy tudunk-e felső korlátot (max) adni a halmazban tárolandó természetes számokra. Általában, a halmaz elemeit egy sorozat fogja tárolni. Speciálisan, a halmazt egy max+1 méretű logikai értékű tömb reprezentálja úgy, hogy a halmaz elemei a tömb azon indexei lesznek, ahol a tömb igaz értéket tárol. o Szeretnénk a reprezentációt elrejteni a halmazt használók elől: egy halmaz létrehozásánál csak azt kérdezzük meg, hogy tud-e a felhasználó felső korlátot mondani a halmazba kerülő természetes számokra, de nem kell tudnia arról, hogy ehhez milyen reprezentációt használunk. 2

Kétféle reprezentáció insert remove select Sorozat Tömb 4 1 0 empty setempty in 1 seq 1 4 0 size 0 1 max vect true true false false true false 4 size 3 1. Dinamikusan változó hosszúságú sorozat. 2. Műveletek számítási bonyolultsága többnyire lineáris, de az empty és a select konstans idejű. 1. Rögzített méretű tömb és külön a halmazbeli elemek száma. 2. Műveletek számítási bonyolultsága többnyire konstans, de a select és a setempty lineáris. 3

reprezentáció típusértékek Halmaz típus sorozattal set(n) Olyan véges elemű halmazok, amelynek elemei természetes számok. Típus-specifikáció üresé teszi a halmazt (setempty) h:= h:set(n) betesz egy elemet a halmazba (insert) h:=h {e h:set(n), e:n kivesz egy elemet a halmazból (remove) h:=h {e h:set(n), e:n kiválasztja a halmaz egy elemét (select) e:=mem(h) h:set(n), e:n üres-e a halmaz (empty) l:= h= h:set(n), l:l benne van-e egy elem a halmazban (in) l:= e h h:set(n), e:n, l:l műveletek seq : N* C++-ban: vector<int> műveletek programjai implementáció Típus-megvalósítás 4

Sorozattal reprezentált halmaz műveletei h:= seq := <> e := seq[1] e := mem(h) seq >0 l := h= l := seq = 0 l := e h l, ind:=search i=1.. seq (seq[i]=e) h := h {e l, ind:=search i=1.. seq (seq[i]=e) l lineáris keresés h := h {e l, ind:=search i=1.. seq (seq[i]=e) l seq := seq <e> seq[ind] := seq[ seq ] seq := seq [1.. seq -1] seq.push_back(e) seq.pop_back() 5

reprezentáció típusértékek Halmaz típus tömbbel set([0..max]) Olyan halmazok, amelynek elemei 0 és max közé eső természetes számok. Típus-specifikáció üresé teszi a halmazt (setempty) h:= h:set([0..max]) betesz egy elemet a halmazba (insert) h:=h {e h:set([0..max]), e:n kivesz egy elemet a halmazból (remove) h:=h {e h:set([0..max]), e:n kiválasztja a halmaz egy elemét (select) e:=mem(h) h:set([0..max]), e:n üres-e a halmaz (empty) l:= h= h:set([0..max]), l:l benne van-e egy elem a halmazban (in) l:= e h h:set([0..max]), e:n, l:l műveletek vect : L 0..max size : N invariáns: size = Σ i=0..max 1 vect[i] műveletek programjai implementáció Típus-megvalósítás 6

Tömbbel reprezentált halmaz műveletei h:= i = 0.. max összegzés tétele e := mem(h) e := 0 size>0 vect[i] := false vect[e] size:= 0 l := h= l := size=0 h := h {e kiválasztás tétele size = Σ i=0..max 1 vect[i] e := e+1 l := e h l := vect[e] h := h {e vect[e] vect[e] vect[e] := true ++size vect[e] := false --size 7

Halmaz osztály publikus része class Set { Set ; void setempty(); void insert(const int &e); void remove(const int &e); int select() const; bool empty() const; bool in(int e) const; private: Hogyan írható le egyszerre mindkét reprezentáció? + setempty() : void + insert(int) : void + remove(int) : void + select() : int {query + empty() : bool {query + in(int) : bool {query set.h 8

Osztálydiagram 1. változat nincs reprezentáció csak a művelek formája adott, nincs definíciójuk <<interface>> Set + setempty() : void {virtual + insert(int) : void {virtual + remove(int) : void {virtual + select() : int {virtual, query + empty() : bool {virtual, query + in(int) : bool {virtual, query SequenceSet h1; ArraySet h2(15); példányosításkor ilyenkor meg kell adni a reprezentációt de mi inkább ilyet szeretnénk Set h1; Set h2(15); ArraySet - vect : bool[0..max] - size : int + ArraySet(n:int) + setempty() : void {override + insert(int) : void {override + remove(int) : void {override + select() : int {override + empty() : bool {override + in(int) : bool {override SequenceSet - vect : seq(int) + SequenceSet() + setempty() : void {override + insert(int) : void {override + remove(int) : void {override + select() : int {override + empty() : bool {override + in(int) : bool {override 9

Osztálydiagram 2. változat Set h1; Set h2(15); Set referencia vagy pointer <<interface>> SetRepr + Set(n:int = 0) + setempty() : void + insert(int) : void + remove(int): void + select() : int {query + empty() : bool {query + in(int) : bool {query - repr + setempty() : void {virtual + insert(int) : void {virtual + remove(int) : void {virtual + select() : int {query, virtual + empty() : bool {query, virtual + in(int) : bool {query, virtual if n=0 then repr = new SequenceSet; else repr = new ArraySet (n); endif repr.setempty() repr.insert(e) repr.remove(e) return repr.select() return repr.empty() return repr.in(e) ArraySet - vect : bool[0..max] - size : int + ArraySet(int) + insert(int) : void {override + remove(int) : void {override + select() : int {override + empty() : bool {override + in(int) : bool {override SequenceSet - seq : seq(int) + SequenceSet() + insert(int) : void {override + remove(int) : void {override + select() : int {override + empty() : bool {override + in(int) : bool {override 10

Híd (bridge) tervezési minta Egy osztály reprezentációját leválasztjuk az osztályról azért, hogy az rugalmasan kicserélhető legyen. Type method() - repr <<interface>> Representation method() repr.method() RepresentationA method() RepresentationB method() A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 11

Halmaz osztály inline módon #include "setrepr.h" #include "array_set.h" #include "sequence_set.h" class Set { Set(int n = 0) { if (0 == n) _repr = new SequenceSet; else _repr = new ArraySet(n); ~Set() { delete _repr; void setempty() { _repr->setempty(); void insert(int e) { _repr->insert(e); void remove(int e) { _repr->remove(e); int select() const { return _repr->select(); bool empty() const { return _repr->empty(); bool in(int e) const { return _repr->in(e); private: SetRepr *_repr; ; pointer Set(const Set& h); Set& operator=(const Set& h); Set + Set(n:int = 0) + setempty() : void + insert(int) : void + remove(int) : void + select() : int {query + empty() : bool {query + in(int) : bool {query Az alapértelmezett másoló konstruktor és értékadás operátor rosszul működne, de ha privátok, akkor nem használhatók. Később felülírhatjuk és publikussá tehetjük. set.h 12

Kitérő: amikor az alapértelmezett másolás és értékadás rossz class Set { Set(int n = 0) { if (0 == n) _repr = new SequenceSet; else _repr = new ArraySet(n); ~Set() { delete _repr; private: SetRepr *_repr; ; verem memória (STACK) b Set _repr : :Set cím a Set cím : Set _repr : Set a, b; b = a; értékadás operátor dinamikus memória (HEAP) : SequenceRepr sekélymásolás : SequenceRepr memória szivárgást Set b = a; másoló konstruktor mélymásolás kellene 13

Reprezentáció interfésze <<interface>> SetRepr + setempty() : void {virtual + insert(int) : void {virtual + remove(int) : void {virtual + select() : int {virtual, query + empty() : bool {virtual, query + in(int) : bool {virtual, query class SetRepr { virtual void setempty() = 0; virtual void insert(int e) = 0; virtual void remove(int e) = 0; virtual int select() const = 0; virtual bool empty() const = 0; virtual bool in(int e) const = 0; virtual ~SetRepr(){ ; setrepr.h 14

Sorozat-reprezentáció #include "setrepr.h" #include <vector> class SequenceSet : public SetRepr{ SequenceSet ():SetRepr() { setempty(); void setempty() override; void insert(int e) override; void remove(int e) override; int select() const override; bool empty() const override; bool in(int e) const override; private: std::vector<int> _seq; bool search(int e, unsigned int &ind) const; ; sequence_set.h <<interface>> SetRepr + setempty() : void {virtual + insert(int) : void {virtual + remove(int) : void {virtual + select() : int {virtual, query + empty() : bool {virtual, query + in(int) : bool {virtual, query SequenceSet - seq : seq(int) + SequenceSet() + insert(int) : void {override + remove(int) : void {override + select() : int {override + empty() : bool {override + in(int) : bool {override 15

Tömb-reprezentáció <<interface>> SetRepr #include "setrepr.h" #include <vector> class ArraySet : public SetRepr{ ArraySet (int n) : SetRepr(), _vect(n+1), _size(0) { setempty(); void setempty() override; void insert(int e) override; void remove(int e) override; int select() const override; bool empty() const override; bool in(int e) const override; private: std::vector<bool> _vect; int _size; ; array_set.h + setempty() : void {virtual + insert(int) : void {virtual + remove(int) : void {virtual + select() : int {virtual, query + empty() : bool {virtual, query + in(int) : bool {virtual, query ArraySet - vect : bool[0..max] - size : int + ArraySet(int) + insert(int) : void {override + remove(int) : void {override + select() : int {override + empty() : bool {override + in(int) : bool {override 16

Kivételek dobása int Set::select() const { if (empty()) throw EmptySetException(); return repr->select(); set.h Set h(100); try { h.insert(101); int e = h.select() catch(std::exception &ex){ cout << ex.what() << endl; kivétel példányosítás és dobás bool ArraySet::in(int e) const { if (e<0 e>int(vect.size())-1) throw IllegalElementException(e); return _vect[e]; bool ArraySet::insert(int e) const { if (e<0 e>int(vect.size())-1) throw IllegalElementException(e); return _vect[e]; array_set.cpp 17

Kivételek osztályai #include <exception> #include <sstream> szabványos kivétel osztályok class EmptySetException : public std::exception { const char* what() const noexcept override { return "Empty set"; ; class IllegalElementException : public std::exception { private: int _e; IllegalElementException(int e): _e(e) { const char* what() const noexcept override { std::ostringstream os; os << "Illegal element: " << _e; std::string str = os.str(); char* msg = new char[str.size() + 1]; std::copy(str.begin(), str.end(), msg); msg[str.size()] = '\0'; return msg; ; setrepr.h 18

2.Feladat Keressünk egy természetes számokat tartalmazó halmazban olyan számot, amely nagyobb a halmaz legalább három másik eleménél! (Ez a keresés biztos sikertelen lesz, ha nincs a halmazban legalább négy szám, és biztosan sikeres, ha van.) o A feladat megoldható a halmaz elemei közti lineáris kereséssel, amely során minden elemnél egy számlálással határozzuk meg azt, hogy hány nálánál kisebb érték van a halmazban. o Mindkét programozási tételhez a halmaz elemeit kell felsorolni. 19

Specifikáció A : h:set(n), l:l, n:n Ef: h = h 0 Uf: l, n = SEARCH e h0 (kisebbekszáma(h 0, e) 3) kisebbekszáma(h 0, e) = u h0 1 e > u bool l = false; int n; for ( ;!l &&!h.empty(); h.remove(h.select())){ n = h.select(); int c = 0; for ( ;!h.empty(); h.remove(h.select())){ if (n > h.select()) ++c; l = c>=3; Ez a megoldás rossz, mert - a két felsorolás nem független: a belső felsoroló nem újrakezdi, hanem folytatja a külső felsorolást, sőt be is fejezi azt, hiszen mindkettő ugyanazokat a műveleteket használja - a felsorolás módosítja a halmazt: a belső ciklus már első alkalommal törli a halmaz összes elemét. a halmaz egy lehetséges felsorolása: first() ~ - current() ~ select() next() ~ remove(select()) end() ~ empty() 20

Bejáró (iterátor) tervezési minta Egy gyűjtemény elemeinek felsorolását (bejárását) egy attól független objektum (felsoroló) végzi, amely eléri a felsorolandó gyűjteményt (hivatkozik rá vagy annak konstans másolatára). A felsoroló objektumot a gyűjtemény hozza létre. Enumerator bejár Collection + first() : void + next() : void + end() : bool {query + current() : int {query * létrehoz + createenumerator() : Enumerator return Enumerator(this) A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 21

Felsorolók <<interface>> Enumerator + first() : void {virtual + next() : void {virtual + end() : bool {virtual, query + current() : int {virtual, query Set + Set(n:int = 0)... return repr.createenumerator() + createenumerator() : Enumerator - repr <<interface>> Használjunk olyan felsorolást, SetRepr amely közvetlenül a reprezentációval dolgozik... + createenumerator() : Enumerator {virtual SequenceSetEnor - ind : int + first() : void {override + next(): void {override + end() : bool {override + current(): int {override * ArraySetEnor - ind : int + first() : void {override + next(): void {override + end() : bool {override + current(): int {override * ArraySet + createenumerator() : ArraySetEnor {override return new ArraySetEnor(this) SequenceSet + createenumerator() : SequenceSetEnor {override return new SequenceSetEnor(this) 22

Gyártófüggvény (factory method) tervezési minta A kliens nem tudja, milyen típusú termék-objektumot kell létrehoznia, és ezt a felelősséget átruházza a segítő alosztályok egyikére. Client Product Creator create():product compose() o = create() Product2 Product1 Creator1 create():product Creator2 create():product return new Product1() return new Product2() A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 23

SequenceSet felsorolója class SequenceSet{ class SequenceSetEnor : public Enumerator{ SequenceSetEnor(SequenceSet *h): _s(h) { void first() override { _ind = 0; void next() override { ++_ind; bool end() const override { return _ind ==_s->_seq.size(); int current() const override { return _s->_seq[_ind]; private: SequenceSet *_s; unsigned int _ind; ; A halmaz elemeinek felsorolását a halmazt reprezentáló sorozat elemeinek felsorolása valósítja meg. Enumerator* createenumerator() override{ return new SequenceSetEnor(this); private: std::vector<int> _seq; <<interface>> Enumerator + first() : void {virtual + next() : void {virtual + end() : bool {virtual, query + current() : int {virtual, query SequenceSetEnor - s : SequenceSet - ind : int + first() : void {override + next(): void {override + end() : bool {override + current(): int {override A beágyazott olyan mintha friend lenne: ; sequence_set.h látja a beágyazó osztály rejtett tagjait is. 24

ArraySet felsorolója class ArraySet{ class ArraySetEnor : public Enumerator{ ArraySetEnor(ArraySet *h): _s(h) { void first() override { _ind = -1; next(); void next() override { for (++_ind;_ind<_s->_vect.size() &&!_s->_vect[_ind]; ++_ind); bool end() const override {return _ind==_s->_vect.size(); int current() const override {return _ind; private: A halmaz elemeinek felsorolását ArraySet *_s; a halmazt reprezentáló tömb unsigned int _ind; ; true értékeihez tartozó indexek felsorolása valósítja meg. <<interface>> Enumerator + first() : void {virtual + next() : void {virtual + end() : bool {virtual, query + current() : int {virtual, query ArraySetEnor - s : SequenceSet - ind : int + first() : void {override + next(): void {override + end() : bool {override + current(): int {override Enumerator* createenumerator() override{ return new ArraySetEnor(this); private: std::vector<bool> _vect; int _size; ; array_set.h 25

Főprogram Set h; // Beolvasás háttérben: a repr >createenumerator() hatására return new SequenceSetEnor(this) fut le Enumerator* enor1 = h.createenumerator(); bool l = false; for (enor1->first();!l &&!enor1->end(); enor1->next()){ int n = enor1->current(); int c = 0; Enumerator* enor2 = h.createenumerator(); for (enor2->first();!enor2->end(); enor2->next()){ if (n > enor2->current()) ++c; l = c>=3; if (l) cout << "A keresett szám: " << n << endl; else cout << "Nincs keresett szám.\n"; main.cpp 26

3.Feladat Tegyük biztonságossá a felsorolást! o Probléma: ha a felsorlás közben olyan műveletet (setempty(), insert(), remove(), értékadás operátor, destruktor) hajtunk végre, amelyik megváltoztatja a halmazt, akkor felsorolás elromolhat. o Megoldás: Zárjuk ki az ilyen műveleteket végrehajtását felsorolás közben. Set h; Enumerator * enor = h.createenumerator(); for (enor->first();!enor->end(); enor->next()){ h.remove(enor->current()); Hibát okozhat a felsorolás során végrehajtott törlés illetve általában minden, a halmazt megváltoztató művelet. 27

Kizárás megvalósítása class Set { void Set::remove(int e) { if (_repr->getenumcount()!=0) throw UnderTraversalException(); _ref->remove(e); ; set.h Set h; try { h.remove(enor->current()); catch(std::exception &ex){ cout << ex.what() << endl; A kritikus művelet akkor dobjon kivételt, ha az adott halmazon éppen felsoroló dolgozik. Ehhez ismerni kell a halmazon dolgozó felsorolók számát. már nem interfész, de még absztrakt osztály class SetRepr { SetRepr(): _enumeratorcount(0){ int getenumcount() const { return _enumeratorcount; protected: int _enumeratorcount; ; class UnderTraversalException : public std::exception { const char* what() const noexcept override { return "Under traversal"; ; setrepr.h aktív felsorolók száma setrepr.h 28

Felsoroló-számlálás a SequenceSet-ben class SequenceSet : public SetRepr{ SequenceSet() : SetRepr() { setempty(); class SequenceSetEnor : public Enumerator{ SequenceSetEnor(SequenceSet *h): _s(h) { ++(_s->_enumeratorcount); ~ SequenceSetEnor() { --(_s->_enumeratorcount); ; lenullázza a felsorolók számlálóját Amikor egy új felsorolót példányosítunk egy SequenceSet objektumhoz, akkor annak felsoroló-számlálóját növeljük. A felsoroló megszűnésekor a felsoroló-számlálót csökkentjük. Enumerator* createenumerator() override { return new SequenceSetEnor(this); ; sequence_set.h 29

Felsoroló-számlálás az ArraySet-ben class ArraySet : public SetRepr { ArraySet(int n) : SetRepr(), _vect(n+1), _size(0) { setempty(); class ArraySetEnor : public Enumerator{ ArraySetEnor(ArraySet *h): _s(h) { ++(_s->_enumeratorcount); ~ArraySetEnor() { --(_s->_enumeratorcount); ; lenullázza a felsorolók számlálóját Amikor egy új felsorolót példányosítunk egy ArraySet objektumhoz, akkor annak felsoroló-számlálóját megnöveljük. a felsoroló megszűnésekor a felsoroló-számlálót csökkentjük Enumerator * createenumerator() override { return new ArraySetEnor(this); ; array_set.h 30

4.Feladat Ne csak integereket lehessen a halmazainkban tárolni. Az osztályok helyett használjunk osztálysablonokat, amelyeknél partaméterként adhassuk meg a halmazban tárolt elemek típusát. Vegyük figyelembe, hogy a tömbös reprezentációval kizárólag a felső korláttal rendelkező természetes számokat tároló halmazokat tudunk ábrázolni, azaz ebben az esetben a sablonparaméter csak int lehet. Set<int> h1(100); Set<int> h2; Set<string> h3; h1.insert(42); h2.insert(1456); h3.insert("alma"); fordítási időben osztályként példányosodik az osztálysablon futási időben objektumként példányosodik az osztály A felsoroló osztályok is osztálysablonok példányai lesznek, amelyek típusparaméterét egyeztetni kell a halmazéval. Enumerator<int> *enor1 = h1.createenumerator(); Enumerator<string> *enor2 = h3.createenumerator(); main.cpp 31

Sablonok <<interface>> Enumerator + first() : void {virtual + next() : void {virtual + end() : bool {virtual, query + current() : Item {virtual, query Item SequenceSetEnor - ind : int * Set + setempty() : void + insert(item) : void + remove(item) : void + select() : Item {query + empty() : bool {query + in(item) : bool {query + createenumerator() : Enumerator Item Item = int ArraySetEnor - ind : int * Item Item = int ArraySet + createenumerator() : ArraySetEnor {override -repr SetRepr Item # enumeratorcount : int + SetRepr() { enumeratorcount=0 + setempty() : void {virtual + insert(item) : void {virtual + remove(item) : void {virtual + select() : Item {virtual, query + empty() : bool {virtual, query + in(item) : bool {virtual, query + createenumerator() : Enumerator {virtual + getenumcount() : int { query SequenceSet Item + createenumerator() : SequenceSetEnor {override 32

SetRepr osztály-sablonja jelöli a sablont, megadja a sablon paramétereit template <typename Item> class SetRepr { SetRepr() : _enumeratorcount(0) { virtual ~SetRepr(){; virtual void setempty() = 0; virtual void insert(item e) = 0; virtual void remove(item e) = 0; virtual Item select() const = 0; virtual bool empty() const = 0; virtual bool in(item e)const = 0; virtual Enumerator<Item>* createenumerator() = 0; int getenumcount() const { return _enumeratorcount; protected: int _enumeratorcount; ; Item SetRepr # enumeratorcount : int + SetRepr() { enumeratorcount=0 + setempty() : void {virtual + insert(item) : void {virtual + remove(item) : void {virtual + select() : Item {virtual, query + empty() : bool {virtual, query + in(item) : bool {virtual, query + createenumerator() : Enumerator {virtual + getenumcount() : int { query setrepr.h 33

SequenceSet osztály-sablonja template <typename Item> class SequenceSet : public SetRepr<Item>{ SequenceSet () : SetRepr<Item> { setempty(); void setempty() override; void insert(item e) override; void remove(item e) override; Item select() const override; bool empty() const override; bool in(item e)const override; private: std::vector<item> _seq; bool search(item e, unsigned int &ind) const; ; Ugyanabba az állományba kerül az osztálysablon definíciója (.h) és a sablon-metódusainak definíciója (.cpp). sequence_set.hpp SetRepr Item Item SequenceSet - seq : seq(item) + SequenceSet() + setempty() : void + insert(item) : void + remove(item) : void + select() : Item {query + empty() : bool {query + in(item) : bool {query - search(int,int) : bool {query + createenumerator() : Sequence SetEnor {override 34

SequenceSet metódus-sablonjai Nemcsak egy osztály, hanem egy függvény is lehet sablon, mint ahogy egy sablonosztály metódusai is sablonok. template <typename Item> void SequenceSet<Item>::insert(int e) { unsigned int ind; if (!search(e,ind)) _seq.push_back(e); template <typename Item> void SequenceSet<Item>::remove(int e) { unsigned int ind; if (search(e,ind)){ _seq[ind] = _seq[_seq.size()-1]; _seq.pop_back(); template <typename Item> int SequenceSet<Item>::select() const { return _seq[0]; sequence_set.hpp 35

Enumerator interfész-sablon <<interface>> Enumerator Item + first() : void {virtual + next() : void {virtual + end() : bool {virtual, query + current() : Item {virtual, query template <typename Item> class Enumerator { virtual void first() = 0; virtual void next() = 0; virtual bool end() const = 0; virtual Item current() const = 0; virtual ~Enumerator(){; ; enumerator.h 36

SequenceSetEnor osztály-sablonja a beágyazás miatt ez is egy Item típus-paraméterű sablon, de nem template <typename Item> kell kiírni újra, hogy ez egy template class SequenceSet : public SetRepr<Item>{ SequenceSet () : SetRepr<Item> { setempty(); class SequenceSetEnor : public Enumerator<Item>{ SequenceSetEnor(SequenceSet<Item> *h): _s(h) { void first() override { _ind = 0; void next() override { ++_ind; bool end() const override { return _ind ==_s->_seq.size(); Item current() const override { return _s->_seq[_ind]; private: SequenceSet<Item> *_s; unsigned int _ind; ; <<interface>> Enumerator Item SequenceSetEnor - s : SequenceSet - ind : int + first() : void {override + next() : void {override + end() : bool {override + current() : Item {override Enumerator<Item>* createenumerator() override{ return new SequenceSetEnor<Item> (this); ; sequence_set.hpp Item 37

ArraySet és ArraySetEnor osztály Sem az ArraySet, sem az ArraySetEnor nem változik, kivéve, hogy a SetRepr helyett a SetRepr<int>-ből, illetve az Enumerator helyett az Enumerator<int>ből származnak. class ArraySet : public SetRepr<int>{ ArraySet (int n): SetRepr<int>(), _vect(n+1), _size(0) { setempty(); class ArraySetEnor : public Enumerator<int>{ ; Enumerator<int>* createenumerator() override{ return new ArraySetEnor(this); ; array_set.hpp 38

Set osztály-sablon template <typename Item> class Set { Set(int n = 0) { Fordítási hiba: Ha Item nem az int (pl. Set<string> esetén), ez az értékadás hibás lesz, mert az ArraySet nem a leszármazottja a SetRepr<string>-nek, ami ilyenkor a _repr típusa. if (0 == n) _repr = new SequenceSet<Item>; else _repr = new ArraySet(n); ~Set() { delete _repr; void setempty() { _repr->setempty(); void insert(item e) { _repr->insert(e); void remove(item e) { _repr->remove(e); Item select() const { return _repr->select(); bool empty() const { return _repr->empty(); bool in(item e)const { return _repr->in(e); Enumerator<Item>* createenumerator() { _repr->createenumerator(); private: SetRepr<Item> *_repr; Set(const Set& h) ; Set& operator=(const Set& h); ; set.h Set + Set(n:int = 0) + setempty() : void + insert(item) : void + remove(item) : void + select() : Item {query + empty() : bool {query + in(item) : bool {query Item Viszont erre az ágra csak Item=int esetén lenne szükség. Csak ekkor kellene lefordítani. 39

Elágazás szerinti példányosítás helyett paraméter függő példányosítás template <typename Item> class Set { Set(int n = 0) { _repr = createsetrepr<item>(n); private: SetRepr<Item>* _repr; Ez egy olyan gyártófüggvény-sablon, amelynek két definíciója is van: egy általános, és egy speciális arra az esetre, ha Item=int. általános osztályszintű gyártófüggvény-sablon static SetRepr<Item>* createsetrepr(int n) { return new SequenceSet<Item>; ; set.h speciális osztályszintű gyártófüggvény-sablon template specializációval template<> SetRepr<int>* Set<int>::createSetRep(int n) { if (0 == n) return new SequenceSet<int>; else return new ArraySet(n); set.h 40