sources:
C2_1.cpp (2.2k)
C2_1.h (1.4k)
C2_1Dlg.cpp (6.8k)
C2_1Dlg.h (1.7k)
Moment.cpp (5.7k)
Moment.h (2.7k)
PolymorphicSet.h (9.8k)
StdAfx.cpp (208 bytes)
StdAfx.h (1.1k)
resource.h (774 bytes)


binaries:
Release/C2_1.exe (28.0k)


website:
more info here
studies/bauelemente/Softwarebauelemente-CodeC2-1/PolymorphicSet.h
download file

  1 ///////////////////////////////////////////////////////////
  2 // Softwarebauelemente II, C2.1
  3 //
  4 // A template for polymorphic set - designed in MFC-style
  5 // The only parameter is the base class of all elements
  6 // (at least CObject)
  7 // All elements are copied by the interface methods
  8 // to avoid unexpected behaviour (e.g. external erase)
  9 //
 10 // author: Stephan Brumme
 11 // last changes: August 3, 2001
 12
 13 #if !defined(AFX_POLYMORPHICSET_H__BA324DAE_872B_11D5_9BB8_AB7BB57BD00C__INCLUDED_)
 14 #define AFX_POLYMORPHICSET_H__BA324DAE_872B_11D5_9BB8_AB7BB57BD00C__INCLUDED_
 15
 16
 17 #include "stdafx.h"
 18
 19
 20 #if _MSC_VER > 1000
 21 #pragma once
 22 #endif // _MSC_VER > 1000
 23
 24
 25 template<class C> class CPolymorphicSet : public CObject 
 26 {
 27 public:
 28     // default constructor
 29     CPolymorphicSet();
 30     // copy constructor
 31     CPolymorphicSet(const CPolymorphicSet<C>& set);
 32
 33     // destructor
 34     virtual ~CPolymorphicSet();
 35
 36     // serialization
 37     virtual void Serialize(CArchive &ar);
 38     // invariance
 39     virtual void AssertValid() const;
 40     // dump
 41     virtual void Dump(CDumpContext& dc) const;
 42
 43     // copy the whole set
 44     virtual CPolymorphicSet<C>& operator=(const CPolymorphicSet<C>& set);
 45     virtual CPolymorphicSet<C>& Copy     (const CPolymorphicSet<C>& set);
 46     // compare two sets
 47     // value identity
 48     virtual bool operator==(const CPolymorphicSet<C>& set) const;
 49     virtual bool EqualValue(const CPolymorphicSet<C>& set) const;
 50     // object identity
 51     virtual bool Equal     (const CPolymorphicSet<C>* set) const;
 52
 53     // returns number of stored elements
 54     int Card() const;
 55
 56     // first stored element
 57     C* GetFirst();
 58     // next element
 59     C* GetNext();
 60     // gets the element the cursor points to
 61     C* GetCurrent() const;
 62
 63     // inserts an element
 64     int  Insert(const C* element);
 65     // deletes current element
 66     void Scratch();
 67     // finds an element
 68     bool Find(const C* element);
 69
 70 protected:
 71 // creates a new instance and copies all attributes
 72     C* Clone(const C* element) const;
 73
 74     // deletes the whole set
 75     void ScratchAll();
 76
 77     // stores all elements in a list
 78     CList<C*, C*> m_Set;
 79     // cursor, may be altered at any time
 80     POSITION m_Cursor;
 81
 82 };
 83
 84
 85 ///////////////////////////////////////////////////////////
 86 ///////////////////////////////////////////////////////////
 87 ///////////////////////////////////////////////////////////
 88
 89
 90 // default constructor
 91 template<class C> CPolymorphicSet<C>::CPolymorphicSet()
 92 {
 93     // empty set
 94     m_Cursor = NULL;
 95 }
 96
 97
 98 // copy constructor
 99 template<class C> CPolymorphicSet<C>::CPolymorphicSet(const CPolymorphicSet<C>& set)
100 {
101     operator=(set);
102     m_Cursor = m_Set.GetHeadPosition();
103 }
104
105    
106 // destructor
107 template<class C> CPolymorphicSet<C>::~CPolymorphicSet()
108 {
109     ScratchAll();
110 }
111
112
113 // serialization
114 template<class C> void CPolymorphicSet<C>::Serialize(CArchive &ar)
115 {
116     // do not forget to serialize CObject's data members
117     CObject::Serialize(ar);
118
119     // make use of CArchive's overloaded << and >> operators for *CObject
120
121     if (ar.IsStoring())
122     {
123         // save the set
124
125         // write cardinality
126         ar << m_Set.GetCount();
127
128         // write all elements
129         POSITION pos = m_Set.GetHeadPosition();
130         while (pos != NULL)
131             ar << m_Set.GetNext(pos);
132     }
133     else     {
134         // load set
135
136         // first, delete old set
137         ScratchAll();
138
139         int nCount;
140         // load cardinality
141         ar >> nCount;
142         // load all elements
143         for (int i=0; i<nCount; i++)
144         {
145             C* element;
146             ar >> element;
147             Insert(element);
148             delete element;
149         }
150     }
151 }
152
153
154 // invariance
155 template<class C> void CPolymorphicSet<C>::AssertValid() const {
156     CObject::AssertValid();
157
158     // if the set is empty then cursor must be NULL
159     if (m_Set.IsEmpty())
160     {
161         ASSERT(m_Cursor == NULL);
162         return;
163     }
164
165     // each element may be present in set at most once
166     // cursor must point to an element
167     POSITION pos = m_Set.GetHeadPosition();
168     bool bValidCursor = false;
169     while (pos != NULL)
170     {
171         // element that the cursor points to was found ?
172         if (pos == m_Cursor)
173             bValidCursor = true;
174
175         // get element
176         C* element = m_Set.GetNext(pos);
177         POSITION posfind = pos;
178         // compare to the remaining elements
179         while (posfind != NULL)
180         {
181             C* compare = m_Set.GetNext(posfind);
182             // no two equal elements are allowed
183             ASSERT(!(*element == *compare));
184         }
185     }
186
187     // cursor validated ?
188     ASSERT(bValidCursor);
189 }
190
191
192 // dump
193 template<class C> void CPolymorphicSet<C>::Dump(CDumpContext& dc) const {
194     CObject::Dump(dc);
195
196     dc << Card() << " elements, cursor points to " << m_Cursor << "\n";
197
198     POSITION pos = m_Set.GetHeadPosition();
199     while (pos != NULL)
200         dc << m_Set.GetNext(pos) << "\n";
201 }
202
203
204 // copy the whole set
205 template<class C> CPolymorphicSet<C>& CPolymorphicSet<C>::operator=(const CPolymorphicSet<C>& set)
206 {
207     // delete old elements
208     m_Set.RemoveAll();
209
210     POSITION pos = set.m_Set.GetHeadPosition();
211     while (pos != NULL)
212     {
213         // save current position
214         POSITION cursor = pos;
215
216         // clone each element
217         C* element = set.m_Set.GetNext(pos);
218         C* copy    = Clone(element);
219         m_Set.AddTail(copy);
220
221         // set cursor
222         // we can't use set.m_Cursor directly because we copied all elements
223         // and therefore lost their old memory address
224         if (cursor == set.m_Cursor)
225             m_Cursor = m_Set.GetTailPosition();
226     }
227
228     return *this;
229 }
230
231
232 // see operator=
233 template<class C> CPolymorphicSet<C>& CPolymorphicSet<C>::Copy(const CPolymorphicSet<C>& set)
234 {
235     return operator=(set);
236 }
237
238
239 // compare two sets
240 template<class C> bool CPolymorphicSet<C>::operator==(const CPolymorphicSet<C>& set) const {
241     // the cursors may differ !
242
243     // same number of elements is required
244     if (m_Set.GetCount() != set.m_Set.GetCount())
245         return false;
246
247     // each element of this set must be found in the other set
248     POSITION pos = m_Set.GetHeadPosition();
249     while (pos != NULL)
250     {
251         C* element = m_Set.GetNext(pos);
252         if (!set.m_Set.Find(element))
253             return false;
254     }
255
256     // all elements were found, sets must be equal
257     return true;
258 }
259
260
261 // see operator==
262 template<class C> bool CPolymorphicSet<C>::EqualValue(const CPolymorphicSet<C>& set) const {
263     return operator==(set);
264 }
265
266
267 // object identity
268 template<class C> bool CPolymorphicSet<C>::Equal(const CPolymorphicSet<C>* set) const {
269     return (set == this);
270 }
271
272
273 // returns number of stored elements
274 template<class C> int CPolymorphicSet<C>::Card() const {
275     return m_Set.GetCount();
276 }
277
278
279 // first stored element
280 template<class C> C* CPolymorphicSet<C>::GetFirst()
281 {
282     // set must not be empty
283     ASSERT(!m_Set.IsEmpty());
284
285     // set cursor
286     m_Cursor = m_Set.GetHeadPosition();
287
288     // clone first element
289     return GetCurrent();
290 }
291
292
293 // next element
294 template<class C> C* CPolymorphicSet<C>::GetNext()
295 {
296     // set must not be empty
297     ASSERT(!m_Set.IsEmpty());
298     // cursor must not be at the end of the set
299     ASSERT(m_Cursor != NULL);
300
301     // set cursor
302     m_Set.GetNext(m_Cursor);
303
304     // clone element
305     return GetCurrent();
306 }
307
308
309 // gets the element the cursor points to
310 template<class C> C* CPolymorphicSet<C>::GetCurrent() const {
311     // cursor must not be at the end of the set
312     ASSERT(m_Cursor != NULL);
313
314     // generate copy
315     C* copy = Clone(m_Set.GetAt(m_Cursor));
316
317     return copy;
318 }
319
320
321 // inserts an element
322 template<class C> int CPolymorphicSet<C>::Insert(const C* element)
323 {
324     // don't insert an object twice
325     if (Find(element))
326         return -1;
327    
328     // add a copy to our set, change cursor
329     m_Cursor = m_Set.AddTail(Clone(element));
330
331     // return index in the set
332     return m_Set.GetCount()-1;
333 }
334
335
336 // deletes current element
337 template<class C> void CPolymorphicSet<C>::Scratch()
338 {
339     // cursor must not be at the end of the set
340     ASSERT(m_Cursor != NULL);
341
342     // store current cursor
343     POSITION removepos = m_Cursor;
344     // go on to the next element (else we lose it after erasing this element)
345     m_Set.GetNext(m_Cursor);
346
347     // remove element the cursor pointed to previously
348     delete m_Set.GetAt(removepos);
349     m_Set.RemoveAt(removepos);
350 }
351
352
353 // looks for an element
354 template<class C> bool CPolymorphicSet<C>::Find(const C* element)
355 {
356     // only non-empty sets
357     if (m_Set.IsEmpty())
358         return false;
359
360     // iterate through the whole list
361     POSITION pos = m_Set.GetHeadPosition();
362     while (pos != NULL)
363     {
364         // store position in case we find a match
365         POSITION storepos = pos;
366
367         // get an element we compare to
368         C* compare  = m_Set.GetNext(pos);
369         // equal ?
370         if (*element == *compare)
371         {
372             // yes, set cursor and return "success !"
373             m_Cursor = storepos;
374             return true;
375         }
376     }
377
378     // element is not part of the set
379     return false;
380 }
381
382
383 // creates a new instance and copies all attributes
384 template<class C> C* CPolymorphicSet<C>::Clone(const C* element) const {
385     // create new instance (care for correct class !)
386     C* copy = (C*)element->GetRuntimeClass()->CreateObject();
387     // copy attributes
388     *copy = *element;
389
390     return copy;
391 }
392
393
394 // deletes the whole set
395 template<class C> void CPolymorphicSet<C>::ScratchAll()
396 {
397     while (!m_Set.IsEmpty())
398     {
399         delete m_Set.GetHead();
400         m_Set.RemoveHead();
401     }
402 }
403
404
405 #endif // !defined(AFX_POLYMORPHICSET_H__BA324DAE_872B_11D5_9BB8_AB7BB57BD00C__INCLUDED_)
406
407