数组类的创建(上)
线性表会被误用 线性表会被当做数组用 ---》》数组类
1、 数组类继承图
对象模拟数组的行为
原生数组
- 不会发现是否越界
- 不能直接复制
- 不能提供其长度信息
2、数组类需求分析
- 创建数组类替代C++中的原生数组的使用
- 数组类包含长度信息
- 数组类能够发现数组越界访问
3、Array的设计要点
- 抽象类模板,存储空间的位置和大小由子类完成
- 重载数组操作符,判断访问下标是否合法
- 提供数组长度的抽象访问函数
- 提供数组对象间的复制
template <typename T> class Array : public Object { protected: T* m_array; public: virtual bool set(int i,const T& e) ; virtual bool get(int i,T& e) const; virtual int length() const = 0 ; T* array() const; T& operator [] (int i); T operator [] (int i) const ; };
note:
- T* m_array 指向一段内存空间 该空间保存数组中元素的位置(有可能堆空间也有可能是栈空间)
-
int length() const =0 获取数组长度 设置为纯虚函数则有
- 当前类为抽象父类,用于被继承
- 实现在子类中完成
//Array.h
1 #ifndef _ARRAY_H_ 2 #define _ARRAY_H_ 3 4 #include "Object.h" 5 #include "Exception.h" 6 7 namespace DataStructureLib 8 { 9 template <typename T> 10 class Array : public Object 11 { 12 protected: 13 T* m_array; 14 public: 15 virtual bool set(int i, const T& e) //O(1) 16 { 17 bool ret = ( 0<=i ) && (i < length()); 18 if (ret){ 19 m_array[i] = e; 20 } 21 22 return ret; 23 } 24 25 virtual bool get(int i, T& e) const //O(1) 26 { 27 bool ret = ( 0<=i ) && (i < length()); 28 29 if(ret){ 30 e = m_array[i]; 31 } 32 33 return ret; 34 } 35 36 virtual int length() const = 0; 37 38 //数组访问操作符 39 T& operator[](int i) //O(1) 40 { 41 if (( 0<=i ) && (i < length())){ 42 return m_array[i]; 43 }else{ 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 54 } 55 56 #endif // _ARRAY_H_
4、StaticArray设计要点
- 类模板
- 封装原生数组类
- 使用模板参数决定数组大小(原生数组的表现形式即 StaticArray 里面的一个成员)
- 实现函数返回数组长度
- 拷贝构造和赋值的操作(原生数组不能直接复制)
StaticArray 类的声明
1 template <typename T,int N> 2 class StaticArray : public Array<T> 3 { 4 protected: 5 T m_space[N]; 6 public: 7 StaticArray() ; 8 9 StaticArray(const StaticArray<T,N>& obj); 10 StaticArray<T,N>& operator= (const StaticArray<T,N>& obj); 11 12 int length() const; 13 };
Staticarray.h
1 #ifndef STATICARRAY_H 2 #define STATICARRAY_H 3 #include "array.h" 4 5 namespace DataStructureLib 6 { 7 template <typename T,int N> 8 class StaticArray :public Array<T> 9 { 10 protected: 11 T m_space[N]; 12 public: 13 StaticArray () 14 { 15 this->m_array=m_space; 16 } 17 18 //拷贝构造和赋值 19 StaticArray(const StaticArray<T,N>& obj ) 20 { 21 this->m_array=m_space; 22 for(int i=0;i<N;i++) 23 { 24 this->m_array[i]=obj.m_array[i]; 25 } 26 } 27 28 StaticArray<T,N> operator =(const StaticArray<T,N>& obj) 29 { 30 31 if(this!=&obj) 32 { 33 for(int i=0;i<N;i++) 34 { 35 this->m_array[i]=obj.m_array[i]; 36 } 37 } 38 return *this; 39 } 40 41 int length()const 42 { 43 return N; 44 } 45 }; 46 } 47 #endif // STATICARRAY_H
main.cpp
#include <iostream> #include "Exception.h" #include "staticarray.h" using namespace std; using namespace DTLib; int main() { StaticArray<int,5> s1; for(int i=0;i<s1.length();i++) { s1[i]=i*i; } for(int i=0;i<s1.length();i++) { cout<<s1[i]<<endl; } StaticArray<int ,5> s2; s2=s1; for(int i=0;i<s2.length();i++) { cout<<s2[i]<<endl; } int s3[5]; s3[6]=100;//正常数组越界,不会报错不会异常难以调试 try { s2[6]=0;//越界报异常 } catch(Exception& e) //Exception是一个抽象类 catch(Exception e)会出错 :抽象类不能实例化 所以需要用引用或者指针 { cout<<e.location()<<endl; cout<<e.message()<<endl; } return 0; }
得到