程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 基於stl序列容器實現的通用集合類

基於stl序列容器實現的通用集合類

編輯:關於C語言

在面向對象開發時,對實際問題分析進而抽象出一種類型,往往會考慮到2個方面:1)類型的內部成員和方法的定義描述 2)類型的多實例存取操作。其中第1點是類型本身數據結構的設計,第2點是類型容器數據結構的選擇設計。在stl中,容器有序列式和關聯式兩種,前者代表有vector,list,deque等;後者代表有set,multiset,map,multimap等,對於一個類型的第2點,我們會考慮甚至是反復權衡選擇序列容器還是關聯容器?在確定選擇了一種之後,比如序列式容器,又會進一步的思考是選擇vetor、list、還是deque?實質上對它們的選擇主要取決於應用的需要,比如要求快速訪問就選擇vetor,要求快速插入刪除就選擇list,符合隊列模型就選擇deque。如果對性能要求較高,就得選擇關聯式容器,這樣訪問、插入、刪除元素都能得到較好的性能。如果操作太頻繁,這時set,map還不行,要選擇hash_set,hash_map等。
   本文僅探討序列式容器的選擇應用,對一個類型而言,既選擇了序列式容器,就意味在vector,list,deque間選擇(這裡要說明的是,stack和queue雖然也是序列式容器,但從真正嚴格意義上講,它們只是一種適配器)那麼有沒有辦法作一個通用的包裝類提供給開發者,讓開發者自己根據應用決定選擇具體的容器類型呢?同時這個包裝又不影響原容器的接口使用。關於包裝類的實現,代碼描述如下
  1#ifndef _STL_COLLECTION_H
  2#define _STL_COLLECTION_H
  3
  4#include <memory>
  5#include <vector>
  6
  7 /**
  8    @class STLCollection
  9    @brief 基於STL序列容器實現的通用集合類
 10
 11    * 提供以索引作為外參的以下公共通用接口
 12    *  add    --- 向前或向後增加單個元素
 13    *  insert --- 插入單個元素
 14    *  erase --- 刪除單個或多個元素
 15    *  set    --- 修改某個元素
 16    *  get    --- 獲取某個元素
 17    *  front  --- 獲取第一個元素
 18    *  back  --- 獲取最後一個元素
 19*/
 20template<typename T,template<class T,class U > class C = std::vector,template <class T> class U = std::allocator>
 21class STLCollection : public C<T,U<T> >
 22{
 23    typedef U<T> Allocator;
 24    typedef C<T,Allocator> base;
 25
 26public:
 27    //為使用方便,重新定義實現構造函數及拷貝構造函數,但賦值拷貝可以不用重新定義實現
 28    STLCollection()
 29    {
 30    }
 31    explicit STLCollection(const Allocator& al)
 32        :base(al)
 33    {
 34    }
 35    explicit STLCollection(size_t n)
 36        :base(n)
 37    {
 38    }
 39    STLCollection(size_t n,const T& t)
 40        :base(n,t)
 41    {
 42    }
 43    STLCollection(size_t n,const T& t,const Allocator& al)
 44        :base(n,t,al)
 45    {
 46    }
 47    STLCollection(const STLCollection& right)
 48        :base(right)
 49    {
 50    }
 51
 52    template<class InputIterator>
 53    STLCollection(InputIterator first,InputIterator last)
 54        :base(first,last)
 55    {
 56    }
 57
 58    template<class InputIterator>
 59    STLCollection(InputIterator first,InputIterator last,const Allocator& al)
 60        :base(first,last,al)
 61    {
 62    }
 63
 64public:
 65    //使基類的同名函數erase,insert,front,back可見
 66    using base::erase;
 67    using base::insert;
 68    using base::front;
 69    using base::back;
 70
 71    void add(const T& t,bool append = true)
 72    {
 73        if (append)
 74            base::insert(base::end(),t);
 75        else
 76            base::insert(base::begin(),t);
 77    }
 78    void insert(size_t index,const T& t)
 79    {
 80        insert_impl(index,t,typename std::iterator_traits<typename base::iterator>::iterator_category());
 81    }
 82    void erase(size_t index)
 83    {
 84        erase_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
 85    }
 86    void erase(size_t beg,size_t end)
 87    {
 88        erase_impl(beg,end,typename std::iterator_traits<typename base::iterator>::iterator_category());
 89    }
 90    void set(size_t index,const T& t)
 91    {
 92        T* p = get(index);
 93        if (p) *p = t;
 94    }
 95    T* get(size_t index)
 96    {
 97        return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
 98    }
 99    const T* get(size_t index) const
100    {
101        return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
102    }
103    T* front()
104    {
105        if (base::empty()) return NULL;
106        return &base::front();
107    }
108    const T* front() const
109    {
110        if (base::empty()) return NULL;
111        return &base::front();
112    }
113    T* back()
114    {
115        if (base::empty()) return NULL;
116        return &base::back();
117    }
118    const T* back() const
119    {
120        if (base::empty()) return NULL;
121        return &base::back();
122    }
123    bool is_empty() const
124    {
125        return base::empty();
126    }
127
128private:
129    /*************************************************************************************
130        下面函數僅作內部實現,需要注意以下幾點
131        (1) 不讓其子類和外部可見,故使用private訪問控制
132        (2) 考慮到子類可能會使用using指令來引用,如果為重載形式,子類using引用同名函數
133             會因為private出錯而不能引用public同名函數,故特命名為xxx_impl而非重載形式
134    *************************************************************************************/
135    void insert_impl(size_t index,const T& t,std::random_access_iterator_tag tag)
136    {
137        if (index < base::size())
138        {
139            base::insert(base::begin()+index,t);
140        }
141    }
142    void insert_impl(size_t index,const T& t,std::input_iterator_tag tag)
143    {
144        if (index < base::size())
145        {
146            typename base::iterator it = base::begin();
147            while(index--) ++it;
148            base::insert(it,t);
149        }
150    }
151    void erase_impl(size_t index,std::random_access_iterator_tag tag)
152    {
153        if (index < base::size())
154        {
155            base::erase(base::begin()+index);
156        }
157    }
158    void erase_impl(size_t index,std::input_iterator_tag tag)
159    {
160        if (index < base::size())
161        {
162            typename base::iterator it = base::begin();
163            while(index--) ++it;
164            base::erase(it);
165        }
166    }
167    void erase_impl(size_t beg,size_t end,std::random_access_iterator_tag tag)
168    {
169        end = std::min(end,base::size());
170        if (beg < end)
171        {
172            base::erase(base::begin()+beg,base::begin()+end);
173        }
174    }
175    void erase_impl(size_t beg,size_t end,std::input_iterator_tag tag)
176    {
177        end = std::min(end,base::size());
178        if (beg < end)
179        {
180            typename base::iterator it = base::begin();
181            while(beg++ < end) it = base::erase(it);
182        }
183    }
184    T* get_impl(size_t index,std::random_access_iterator_tag tag)
185    {
186        if (index>=base::size())
187            return NULL;
188        return &(*(base::begin()+index));
189    }
190    const T* get_impl(size_t index,std::random_access_iterator_tag tag) const
191    {
192        if (index>=base::size())
193            return NULL;
194        return &(*(base::begin()+index));
195    }
196    T* get_impl(size_t index,std::input_iterator_tag tag)
197    {
198        if (index>=base::size())
199            return NULL;
200        typename base::iterator it = base::begin();
201        while (index--) ++it;
202        return &(*it);
203    }
204    const T* get_impl(size_t index,std::input_iterator_tag tag) const
205    {
206        if (index>=base::size())
207            return NULL;
208        typename base::const_iterator it = base::begin();
209        while(index--) ++it;
210        return &(*it);
211    }
212};
213
214#endif
   這樣一來,由於STLCollection類提供了通用的操作接口,在應用時如果想切換改變為另一種容器,只需改變第2個模板參數即可,其它部分代碼都不用改變,大大方便了程序的維護擴展,還可以繼承STLCollection類,實現自己特殊的集合類,比如元素類型是_variant_t類型,代碼描述如下
  1#ifndef _VARIANT_COLLECTION_H
  2#define _VARIANT_COLLECTION_H
  3
  4#include <comutil.h>
  5#pragma comment(lib,"comsuppw.lib")
  6
  7class variant_collection : public STLCollection<_variant_t>
  8{
  9    typedef STLCollection<_variant_t> base;
 10
 11public:
 12    using base::add;
 13    using base::insert;
 14    using base::set;
 15
 16    void add(signed char val)
 17    {
 18        add<signed char>(val);
 19    }
 20    void add(unsigned char val)
 21    {
 22        add<unsigned char>(val);
 23    }
 24    void add(short val)
 25    {
 26        add<short>(val);
 27    }
 28    void add(unsigned short val)
 29    {
 30        add<unsigned short>(val);
 31    }
 32    void add(int val)
 33    {
 34        add<int>(val);
 35    }
 36    void add(unsigned int val)
 37    {
 38        add<unsigned int>(val);
 39    }
 40    void add(float val)
 41    {
 42        add<float>(val);
 43    }
 44    void add(double val)
 45    {
 46        add<double>(val);
 47    }
 48    void add(const char* val)
 49    {
 50        add<const char*>(val);
 51    }
 52 
 53    void insert(size_t index,signed char val)
 54    {
 55        insert<signed char>(index,val);
 56    }
 57    void insert(size_t index,unsigned char val)
 58    {
 59        insert<unsigned char>(index,val);
 60    }
 61    void insert(size_t index,short val)
 62    {
 63        insert<short>(index,val);
 64    }
 65    void insert(size_t index,unsigned short val)
 66    {
 67        insert<unsigned short>(index,val);
 68    }
 69    void insert(size_t index,int val)
 70    {
 71        insert<int>(index,val);
 72    }
 73    void insert(size_t index,unsigned int val)
 74    {
 75        insert<unsigned int>(index,val);
 76    }
 77    void insert(size_t index,float val)
 78    {
 79        insert<float>(index,val);
 80    }
 81    void insert(size_t index,double val)
 82    {
 83        insert<double>(index,val);
 84    }
 85    void insert(size_t index,const char* val)
 86    {
 87        insert<const char*>(index,val);
 88    }
 89  
 90    void set(size_t index,signed char val)
 91    {
 92        set<signed char>(index,val);
 93    }
 94    void set(size_t index,unsigned char val)
 95    {
 96        set<unsigned char>(index,val);
 97    }
 98    void set(size_t index,short val)
 99    {
100        set<short>(index,val);
101    }
102    void set(size_t index,unsigned short val)
103    {
104        set<unsigned short>(index,val);
105    }
106    void set(size_t index,int val)
107    {
108        set<int>(index,val);
109    }
110    void set(size_t index,unsigned int val)
111    {
112        set<unsigned int>(index,val);
113    }
114    void set(size_t index,float val)
115    {
116        set<float>(index,val);
117    }
118    void set(size_t index,double val)
119    {
120        set<double>(index,val);
121    }
122    void set(size_t index,const char* val)
123    {
124        set<const char*>(index,val);
125    }
126
127protected:
128    template<typename T>
129    void add(T val)
130    {
131        _variant_t var(val);
132        base::add(var);
133    }
134    template<typename T>
135    void insert(size_t index,T val)
136    {
137        _variant_t var(val);
138        base::insert(index,var);
139    }
140    template<typename T>
141    void set(size_t index,T val)
142    {
143        _variant_t* p_var = base::get(index);
144        if (p_var) *p_var = val;
145    }
146};
147
148#endif

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved