在做ProE二次开发的时候,时常会用到数组ProArray,虽然掌握之后并不难,但是用法毕竟不简洁,有时候难免出错,比如用ProArrayAlloc申请了一数组,但忘了释放,这就会导致内存泄露,等等。
我们知道,C++的标准库STL中有vector,完全可以替代C中难用的原生数组,所以我想,可不可以写一个类似vector的类来封装ProArray呢?
经过一段时间的编码,终于完成了这个类似vector的CProArray类,代码如下:
CProArray.h
1 #ifndef _C_PRO_ARRAY_H_ 2 #define _C_PRO_ARRAY_H_ 3 4 #include <ProToolkit.h> 5 #include <ProArray.h> 6 #include <exception> 7 #include <stdexcept> 8 9 using std::exception; 10 using std::out_of_range; 11 using std::bad_alloc; 12 13 template<class TYPE, size_t reallocationSize> 14 class CProList; 15 16 template<class TYPE, size_t reallocationSize = 5> 17 class CProArray 18 { 19 friend class CProList<TYPE, reallocationSize>; 20 21 public: 22 CProArray() 23 //throw(bad_alloc) 24 : m_arr(NULL), m_nCntAdd(reallocationSize), use(1) 25 { 26 if (reallocationSize == 0) m_nCntAdd = 5; 27 if (PRO_TK_OUT_OF_MEMORY == ProArrayAlloc(0, sizeof(TYPE), m_nCntAdd, &m_arr)) 28 throw bad_alloc("out of memory."); 29 } 30 31 ~CProArray() 32 { 33 ProArrayFree(&m_arr); 34 } 35 36 CProArray(const CProArray& arrSrc) 37 //throw(bad_alloc) 38 : m_arr(NULL), m_nCntAdd(reallocationSize), use(1) 39 { 40 if (reallocationSize == 0) m_nCntAdd = 5; 41 if (PRO_TK_OUT_OF_MEMORY == ProArrayAlloc(0, sizeof(TYPE), m_nCntAdd, &m_arr)) 42 throw bad_alloc("out of memory."); 43 size_t nSizeSrc = arrSrc.size(); 44 if (0 != nSizeSrc) 45 { 46 if (PRO_TK_OUT_OF_MEMORY == ProArrayObjectAdd(&m_arr, -1, nSizeSrc, arrSrc.m_arr)) 47 throw bad_alloc("out of memory."); 48 } 49 } 50 51 CProArray& operator=(const CProArray& arrSrc) 52 //throw(bad_alloc) 53 { 54 clear(); 55 size_t nSizeSrc = arrSrc.size(); 56 if (0 != nSizeSrc) 57 { 58 if (PRO_TK_OUT_OF_MEMORY == ProArrayObjectAdd(&m_arr, -1, nSizeSrc, arrSrc.m_arr)) 59 throw bad_alloc("out of memory."); 60 } 61 } 62 63 public: 64 size_t size() const 65 { 66 int nSize; 67 ProArraySizeGet(m_arr, &nSize); 68 return nSize; 69 } 70 71 bool is_empty() const 72 { 73 return !size(); 74 } 75 76 void clear() 77 { 78 if (0 != size()) 79 ProArrayObjectRemove(&m_arr, 0, size()); 80 } 81 82 void push_back(const TYPE& val) 83 //throw(bad_alloc) 84 { 85 if (PRO_TK_OUT_OF_MEMORY == ProArrayObjectAdd(&m_arr, -1, 1, (void*)(&val))) 86 throw bad_alloc("out of memory."); 87 } 88 89 void pop_back() 90 { 91 if (!is_empty()) 92 ProArrayObjectRemove(&m_arr, -1, 1); 93 } 94 95 const TYPE& front() const 96 //throw(out_of_range) 97 { 98 if (is_empty()) 99 throw out_of_range("empty CProArray."); 100 return reinterpret_cast<const TYPE*>(m_arr)[0]; 101 } 102 103 TYPE& front() 104 //throw(out_of_range) 105 { 106 return const_cast<TYPE&>(const_cast<const CProArray*>(this)->front()); 107 } 108 109 const TYPE& back() const 110 //throw(out_of_range) 111 { 112 if (is_empty()) 113 throw out_of_range("empty CProArray."); 114 return reinterpret_cast<const TYPE*>(m_arr)[size()-1]; 115 } 116 117 TYPE& back() 118 //throw(out_of_range) 119 { 120 return const_cast<TYPE&>(const_cast<const CProArray*>(this)->back()); 121 } 122 123 const TYPE& operator[](size_t index) const 124 //throw(out_of_range) 125 { 126 if (is_empty()) 127 throw out_of_range("empty CProArray."); 128 if (size() <= index) 129 throw out_of_range("invalid index of CProArray."); 130 return reinterpret_cast<const TYPE*>(m_arr)[index]; 131 } 132 133 TYPE& operator[](size_t index) 134 //throw(out_of_range) 135 { 136 return const_cast<TYPE&>(const_cast<const CProArray*>(this)->operator[](index)); 137 } 138 139 const TYPE& at(size_t index) const 140 //throw(out_of_range) 141 { 142 if (is_empty()) 143 throw out_of_range("empty CProArray."); 144 if (size() <= index) 145 throw out_of_range("invalid index of CProArray."); 146 return reinterpret_cast<const TYPE*>(m_arr)[index]; 147 } 148 149 TYPE& at(size_t index) 150 //throw(out_of_range) 151 { 152 return const_cast<TYPE&>(const_cast<const CProArray*>(this)->at(index)); 153 } 154 155 void insert_at(size_t index, const TYPE& val) 156 //throw(out_of_range, bad_alloc) 157 { 158 if (size() < index) 159 throw out_of_range("invalid index of CProArray."); 160 if (size() == index) 161 index = -1; 162 if (PRO_TK_OUT_OF_MEMORY == ProArrayObjectAdd(&m_arr, index, 1, (void*)(&val))) 163 throw bad_alloc("out of memory."); 164 } 165 166 void insert_at(size_t index, size_t cnt, const TYPE *pVal) 167 //throw(out_of_range, bad_alloc) 168 { 169 if (size() < index) 170 throw out_of_range("invalid index of CProArray."); 171 if (size() == index) 172 index = -1; 173 if (PRO_TK_OUT_OF_MEMORY == ProArrayObjectAdd(&m_arr, index, cnt, (void*)pVal)) 174 throw bad_alloc("out of memory."); 175 } 176 177 void remove_at(size_t index, size_t cnt = 1) 178 //throw(out_of_range) 179 { 180 if (size() <= index) 181 throw out_of_range("invalid index of CProArray."); 182 if (size() - index < cnt) 183 throw out_of_range("count to remove is out of range."); 184 ProArrayObjectRemove(&m_arr, index, cnt); 185 } 186 187 operator ProArray() const 188 { 189 return m_arr; 190 } 191 192 public: 193 ProArray m_arr; 194 private: 195 int m_nCntAdd; 196 size_t use; 197 }; 198 199 #endif
代码说明:
1、该类代码经过我反复测试,应该不存在Bug。
2、该类的方法名完全参考vector类的方法名,内部全部是用ProArray的原生方法实现的。
3、在构造函数中通过ProArrayAlloc申请了内存,在析构函数中通过ProArrayFree释放了内存,所以避免了内存泄露。
4、该类有属性为public的ProArray成员m_arr,如果在某些代码处,需要通过ProArray原生方法操作数组,直接获取该成员即可。
5、该类在使用过程中,若出现访问越界等错误,会抛出异常。
6、该类使用C++的模板元编程实现。
7、由于每个方法代码都很短,所以全部写在头文件中,即全部为内联函数。
使用Demo:
CProArray<int> nArr;
nArr.push_back(6);
nArr.push_back(7);
for (int i=0; i<nArr.size(); ++i)
{
CString cstr;
cstr.Format(TEXT("%d"), nArr[i]);
AfxMessageBox(cstr);
}