在面向对象开发时,对实际问题分析进而抽象出一种类型,往往会考虑到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
5#include
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 class C = std::vector,template class U = std::allocator>
21class STLCollection : public C >
22{
23 typedef U Allocator;
24 typedef C 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
53 STLCollection(InputIterator first,InputIterator last)
54 :base(first,last)
55 {
56 }
57
58 template
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::iterator_category());
81 }
82 void erase(size_t index)
83 {
84 erase_impl(index,typename std::iterator_traits::iterator_category());
85 }
86 void erase(size_t beg,size_t end)
87 {
88 erase_impl(beg,end,typename std::iterator_traits::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::iterator_category());
98 }
99 const T* get(size_t index) const
100 {
101 return get_impl(index,typename std::iterator_traits::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