第十九课 数组类的创建(上)
基于顺序存储结构的线性表可能被当成数组来误用,这一节我们要设计数组类来代替原生数组。
课程目标:
Array是一个抽象类,这个类存在的意义就是用来被继承。
需求分析:
原生数组是不提供复制操作的,我们自己的数组要提供复制操作。
length()成员函数设置为纯虚函数,说明这个类是一个纯虚类,用于被继承,具体实现在子类中完成。
在工程中添加Array.h文件:
1 #ifndef ARRAY_H 2 #define ARRAY_H 3 4 #include "Object.h" 5 #include "Exception.h" 6 7 namespace DTLib 8 { 9 10 template <typename T> 11 class Array : public Object 12 { 13 protected: 14 T* m_array; 15 public: 16 virtual bool set(int i, const T&e) //O(1) 17 { 18 bool ret = ((0 <= i) && (i < length())); 19 20 if( ret ) 21 { 22 m_array[i] = e; 23 } 24 } 25 26 virtual bool get(int i, T& e) const //O(1) 27 { 28 bool ret = ((0 <= i) && (i < length())); 29 30 if( ret ) 31 { 32 e = m_array[i]; 33 } 34 } 35 36 T& operator[] (int i) //O(1) 37 { 38 if((0 <= i) && (i < length())) 39 { 40 return m_array[i]; 41 } 42 else 43 { 44 THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ..."); 45 } 46 } 47 48 T operator[] (int i) const //O(1) 49 { 50 return (const_cast<Array<T>>(*this))[i]; 51 } 52 53 virtual int length() const = 0; 54 }; 55 56 } 57 58 #endif // ARRAY_H
StaticArray设计:
添加StaticArray.h文件,如下:
1 #ifndef STATICARRAY_H 2 #define STATICARRAY_H 3 4 #include "Array.h" 5 6 namespace DTLib 7 { 8 9 template <typename T, int N> 10 class StaticArray : public Array<T> 11 { 12 protected: 13 T m_space[N]; 14 public: 15 StaticArray() //O(1) 16 { 17 this->m_array = m_space; //将定义的原生数组挂接到指针上去 18 } 19 20 StaticArray(const StaticArray<T, N>& obj) //O(n) 21 { 22 this->m_array = m_space; 23 24 for(int i = 0; i < N; i++) 25 { 26 m_space[i] = obj.m_space[i]; 27 } 28 } 29 30 StaticArray<T, N>& operator= (const StaticArray<T, N>& obj) //O(n) 31 { 32 if( this != &obj ) 33 { 34 for(int i = 0; i < N; i++) 35 { 36 m_space[i] = obj.m_space[i]; 37 } 38 } 39 40 return *this; 41 } 42 43 int length() const // O(1) 44 { 45 return N; 46 } 47 }; 48 49 } 50 51 #endif // STATICARRAY_H
测试程序如下:
1 #include <iostream> 2 #include "StaticArray.h" 3 4 5 using namespace std; 6 using namespace DTLib; 7 8 9 int main() 10 { 11 12 StaticArray<int, 5> s1; 13 14 for(int i = 0; i<s1.length(); i++) 15 { 16 s1[i] = i * i; 17 } 18 19 for(int i = 0; i < s1.length(); i++) 20 { 21 cout << s1[i] << endl; 22 } 23 24 return 0; 25 }
运行结果如下:
第16、21行可以使用数组下标访问了,打印结果也是正确的。
第二个测试程序:
1 #include <iostream> 2 #include "StaticArray.h" 3 4 5 using namespace std; 6 using namespace DTLib; 7 8 9 int main() 10 { 11 12 StaticArray<int, 5> s1; 13 14 for(int i = 0; i<s1.length(); i++) 15 { 16 s1[i] = i * i; 17 } 18 19 for(int i = 0; i < s1.length(); i++) 20 { 21 cout << s1[i] << endl; 22 } 23 24 StaticArray<int, 5> s2; 25 26 s2 = s1; 27 28 for(int i = 0; i < s2.length(); i++) 29 { 30 cout << s2[i] << endl; 31 } 32 33 return 0; 34 }
结果如下:
可以看到第26行数组之间的赋值完全是合法的。
修改测试程序:
1 #include <iostream> 2 #include "StaticArray.h" 3 4 5 using namespace std; 6 using namespace DTLib; 7 8 9 int main() 10 { 11 12 StaticArray<int, 5> s1; 13 14 for(int i = 0; i<s1.length(); i++) 15 { 16 s1[i] = i * i; 17 } 18 19 for(int i = 0; i < s1.length(); i++) 20 { 21 cout << s1[i] << endl; 22 } 23 24 StaticArray<int, 5> s2; 25 26 s2 = s1; 27 28 for(int i = 0; i < s2.length(); i++) 29 { 30 cout << s2[i] << endl; 31 } 32 33 s2[6] = 100; 34 35 return 0; 36 }
结果如下:
可以看到33行的越界赋值引发了异常,这样做的好处是在有bug的地方立即抛出异常,而不是等到程序运行了很长时间才出现bug,那时候定位bug是很困难的。
抛出异常这种方式不会引起bug的传播。有问题的地方就立即反应出来。
原生数组是做不到这一点的。
优质内容筛选与推荐>>