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     {
135         // load set
136
137         // first, delete old set
138         ScratchAll();
139
140         int nCount;
141         // load cardinality
142         ar >> nCount;
143         // load all elements
144         for (int i=0; i<nCount; i++)
145         {
146             C* element;
147             ar >> element;
148             Insert(element);
149             delete element;
150         }
151     }
152 }
153
154
155 // invariance
156 template<class C> void CPolymorphicSet<C>::AssertValid() const
157 {
158     CObject::AssertValid();
159
160     // if the set is empty then cursor must be NULL
161     if (m_Set.IsEmpty())
162     {
163         ASSERT(m_Cursor == NULL);
164         return;
165     }
166
167     // each element may be present in set at most once
168     // cursor must point to an element
169     POSITION pos = m_Set.GetHeadPosition();
170     bool bValidCursor = false;
171     while (pos != NULL)
172     {
173         // element that the cursor points to was found ?
174         if (pos == m_Cursor)
175             bValidCursor = true;
176
177         // get element
178         C* element = m_Set.GetNext(pos);
179         POSITION posfind = pos;
180         // compare to the remaining elements
181         while (posfind != NULL)
182         {
183             C* compare = m_Set.GetNext(posfind);
184             // no two equal elements are allowed
185             ASSERT(!(*element == *compare));
186         }
187     }
188
189     // cursor validated ?
190     ASSERT(bValidCursor);
191 }
192
193
194 // dump
195 template<class C> void CPolymorphicSet<C>::Dump(CDumpContext& dc) const
196 {
197     CObject::Dump(dc);
198
199     dc << Card() << " elements, cursor points to " << m_Cursor << "\n";
200
201     POSITION pos = m_Set.GetHeadPosition();
202     while (pos != NULL)
203         dc << m_Set.GetNext(pos) << "\n";
204 }
205
206
207 // copy the whole set
208 template<class C> CPolymorphicSet<C>& CPolymorphicSet<C>::operator=(const CPolymorphicSet<C>& set)
209 {
210     // delete old elements
211     m_Set.RemoveAll();
212
213     POSITION pos = set.m_Set.GetHeadPosition();
214     while (pos != NULL)
215     {
216         // save current position
217         POSITION cursor = pos;
218
219         // clone each element
220         C* element = set.m_Set.GetNext(pos);
221         C* copy    = Clone(element);
222         m_Set.AddTail(copy);
223
224         // set cursor
225         // we can't use set.m_Cursor directly because we copied all elements
226         // and therefore lost their old memory address
227         if (cursor == set.m_Cursor)
228             m_Cursor = m_Set.GetTailPosition();
229     }
230
231     return *this;
232 }
233
234
235 // see operator=
236 template<class C> CPolymorphicSet<C>& CPolymorphicSet<C>::Copy(const CPolymorphicSet<C>& set)
237 {
238     return operator=(set);
239 }
240
241
242 // compare two sets
243 template<class C> bool CPolymorphicSet<C>::operator==(const CPolymorphicSet<C>& set) const
244 {
245     // the cursors may differ !
246
247     // same number of elements is required
248     if (m_Set.GetCount() != set.m_Set.GetCount())
249         return false;
250
251     // each element of this set must be found in the other set
252     POSITION pos = m_Set.GetHeadPosition();
253     while (pos != NULL)
254     {
255         C* element = m_Set.GetNext(pos);
256         if (!set.m_Set.Find(element))
257             return false;
258     }
259
260     // all elements were found, sets must be equal
261     return true;
262 }
263
264
265 // see operator==
266 template<class C> bool CPolymorphicSet<C>::EqualValue(const CPolymorphicSet<C>& set) const
267 {
268     return operator==(set);
269 }
270
271
272 // object identity
273 template<class C> bool CPolymorphicSet<C>::Equal(const CPolymorphicSet<C>* set) const
274 {
275     return (set == this);
276 }
277
278
279 // returns number of stored elements
280 template<class C> int CPolymorphicSet<C>::Card() const
281 {
282     return m_Set.GetCount();
283 }
284
285
286 // first stored element
287 template<class C> C* CPolymorphicSet<C>::GetFirst()
288 {
289     // set must not be empty
290     ASSERT(!m_Set.IsEmpty());
291
292     // set cursor
293     m_Cursor = m_Set.GetHeadPosition();
294
295     // clone first element
296     return GetCurrent();
297 }
298
299
300 // next element
301 template<class C> C* CPolymorphicSet<C>::GetNext()
302 {
303     // set must not be empty
304     ASSERT(!m_Set.IsEmpty());
305     // cursor must not be at the end of the set
306     ASSERT(m_Cursor != NULL);
307
308     // set cursor
309     m_Set.GetNext(m_Cursor);
310
311     // clone element
312     return GetCurrent();
313 }
314
315
316 // gets the element the cursor points to
317 template<class C> C* CPolymorphicSet<C>::GetCurrent() const
318 {
319     // cursor must not be at the end of the set
320     ASSERT(m_Cursor != NULL);
321
322     // generate copy
323     C* copy = Clone(m_Set.GetAt(m_Cursor));
324
325     return copy;
326 }
327
328
329 // inserts an element
330 template<class C> int CPolymorphicSet<C>::Insert(const C* element)
331 {
332     // don't insert an object twice
333     if (Find(element))
334         return -1;
335    
336     // add a copy to our set, change cursor
337     m_Cursor = m_Set.AddTail(Clone(element));
338
339     // return index in the set
340     return m_Set.GetCount()-1;
341 }
342
343
344 // deletes current element
345 template<class C> void CPolymorphicSet<C>::Scratch()
346 {
347     // cursor must not be at the end of the set
348     ASSERT(m_Cursor != NULL);
349
350     // store current cursor
351     POSITION removepos = m_Cursor;
352     // go on to the next element (else we lose it after erasing this element)
353     m_Set.GetNext(m_Cursor);
354
355     // remove element the cursor pointed to previously
356     delete m_Set.GetAt(removepos);
357     m_Set.RemoveAt(removepos);
358 }
359
360
361 // looks for an element
362 template<class C> bool CPolymorphicSet<C>::Find(const C* element)
363 {
364     // only non-empty sets
365     if (m_Set.IsEmpty())
366         return false;
367
368     // iterate through the whole list
369     POSITION pos = m_Set.GetHeadPosition();
370     while (pos != NULL)
371     {
372         // store position in case we find a match
373         POSITION storepos = pos;
374
375         // get an element we compare to
376         C* compare  = m_Set.GetNext(pos);
377         // equal ?
378         if (*element == *compare)
379         {
380             // yes, set cursor and return "success !"
381             m_Cursor = storepos;
382             return true;
383         }
384     }
385
386     // element is not part of the set
387     return false;
388 }
389
390
391 // creates a new instance and copies all attributes
392 template<class C> C* CPolymorphicSet<C>::Clone(const C* element) const
393 {
394     // create new instance (care for correct class !)
395     C* copy = (C*)element->GetRuntimeClass()->CreateObject();
396     // copy attributes
397     *copy = *element;
398
399     return copy;
400 }
401
402
403 // deletes the whole set
404 template<class C> void CPolymorphicSet<C>::ScratchAll()
405 {
406     while (!m_Set.IsEmpty())
407     {
408         delete m_Set.GetHead();
409         m_Set.RemoveHead();
410     }
411 }
412
413
414 #endif // !defined(AFX_POLYMORPHICSET_H__BA324DAE_872B_11D5_9BB8_AB7BB57BD00C__INCLUDED_)
415