20、数组类

/*array需求分析
//创建数组类代替原生数组的使用,数组类包含长度信息,数组类能够主动发现越界访问
设计要点:
抽象类模板,存储空间的位置和大小由子类完成
重载数组操作符,判断访问下标是否合法
提供数组长度的抽象访问函数
提供数组对象间的复制操作
*/
#ifndef ARRAY_H_
#define ARRAY_H_
#include "Wobject.h"
#include "Exception.h"
namespace WSlib
{
template<typename T>
class Array:public Wobject
{
protected:
T* m_array;
public:
virtual bool set(int i,const T& e) //o(1)
{
bool ret=((0<=i)&&(i<length()));
if(ret)
{
m_array[i]=e;
}
return ret;
}
virtual bool get(int i,T& e) const  //o(1)
{
bool ret=((0<=i)&&(i<length()));
if(ret)
{
e=m_array[i];
}
return ret;
}


T& operator[](int i )    //o(1)
{
if((0<=i)&&(i<length()))
{
return m_array[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"PArameter i is invalid...");
}
}
    T operator[](int i) const     //o(1)  为什么返回的不是引用?
{

return (const_cast<Array<T>&>(*this)[i]);
}


virtual int length() const=0;
};
}

#endif

/*StaticArray设计要点
类模板:封装原生数组,使用模板参数决定数组大小,实现函数返回数组长度,拷贝构造和赋值操作*/
#ifndef STATICARRAY_H_
#define STATICARRAY_H_
#include "Array.h"
namespace WSlib
{
template <typename T,int N>
class StaticArray:public Array<T>
{
protected:
T m_space[N];
public:
StaticArray()          //o(1)
{
this->m_array=m_space;
}
StaticArray(const StaticArray<T,N>& obj)   //o(n)
{
this->m_array=m_space;
for(int i=0;i<N;i++)
{
m_space[i]=obj.m_space[i];
}
}
StaticArray<T,N>& operator=(const StaticArray<T,N>& obj)  //o(n)
{
if(this!=&obj)
{
//delete[] m_array; //老师给的没有,不是堆空间,不需要释放
for(int i=0;i<N;i++)
{
m_space[i]=obj.m_space[i];
}
}
return *this;
}
int length()const    //o(1)
{
return N;
}
};
}
#endif
/**********************************************************************************************
#include <iostream>
#include "StaticArray.h"
using namespace WSlib;
using namespace std;
int main()
{
StaticArray <int,5> l;
for(int i=0;i<l.length();i++)
{
l[i]=i*i;
}
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
StaticArray<int,5>s1;
s1=l;
for(int i=0;i<s1.length();i++)
{
cout<<s1[i]<<endl;
}
//s1[6]=100; //异常结束
//int s3[5]; //系统并不会报错
    //s3[8]=100;
return 0;
}

************************************************************************************************/

/*
DynamicArray设计要点
类模板:动态确定内部数组空间的大小,实现函数返回数组长度,拷贝构造和赋值操作
*/
#ifndef DYNAMICARRAY_H_
#define DYNAMICARRAY_H_
#include "Exception.h"
#include "Array.h"
namespace WSlib
{
template <typename T>
class DynamicArray:public Array<T>
{
protected:
int m_length;


//copy:在堆空间中申请新的内存,并执行拷贝操作
T* copy(T* array,int len,int newlen)
{
T* ret=new T[newlen];
if(ret!=NULL)
{
int size=(len<newlen)?len:newlen;
for(int i=0;i<size;i++)
{
ret[i]=array[i];
}
}
return ret;
}
//update:将指定的堆空间作为内部存储数组使用
void update(T* array,int length)
{
if(array!=NULL)
{
T* temp=this->m_array;
this->m_array=array;
this->m_length=length;
delete[] temp;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object...");
}
}
//init:对象构造时的初始化操作
void init(T* array,int length)
{
if(array!=NULL)
{
this->m_array=array;
this->m_length=length;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object...");
}
}
public:
DynamicArray(int length)
{
init(new T[length],length);
/*////////////////////////////////////
this->m_array=new T[length];
if(this->m_array != NULL)
{
this->m_length=length;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object...");
}
*/
}
DynamicArray(const DynamicArray<T>& obj)
{
init(copy(obj.m_array,obj.m_length,obj.m_length) ,obj.m_length);
//T* array=copy(obj.m_array,obj.m_length,obj.m_length);
//init(array ,obj.m_length);
/*////////////////////////////////////////////////////////////////////////////////
this->m_array=new T[obj.m_length];
if(this->m_length != NULL)
{
this->m_length=obj.m_length;
for(int i=0;i<obj.m_length;i++)
{
this->m_array[i]=obj.m_array[i];
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object...");
}
*///////////////////////////////////////////////////////////////////////////
}
DynamicArray<T>& operator=(const DynamicArray<int>& obj)
{
if(this!=&obj)
{
update(copy(obj.m_array,obj.m_length,obj.m_length),obj.m_length);
//T* array=copy(obj.m_array,obj.m_length,obj.m_length);
//update(array,obj.m_length);
///////////////////////////////////////////////////上边是优化
/* T* array=new T[obj.m_length];
if(array !=NULL)
{
for(int i=0;i<obj.m_length;i++)
{
array[i]=obj.m_array[i];
}
T* temp=this->m_array;


this->m_array=array;
this->m_length=obj.m_length;


delete[] temp;  //异常安全
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create copy object...");
}
*/
}
return *this;
}
int length() const
{
return m_length;
}
   
void resize(int length)
{
if(length!=m_length)
{
update(copy(this->m_array,m_length,length),length);
//T* array=copy(this->m_array,m_length,length);
//uapdate(array,length);
///////////////////////////////////////////////////上边优化
/*
T* array=new T[length];
if(array!=NULL)
{
int size=(m_length<length? m_length:length);
for(int i=0;i<size;i++)
{
array[i]=this->m_array[i];
}
T* temp=this->m_array;       //异常安全
this->m_array=array;
this->m_length=length;
delete[] temp;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create resize object...");
}
*/
}
}
~DynamicArray()
{
delete[] this->m_array;
}
};
}
#endif
/*DynamicArray 类中的函数实现存在重复的逻辑,如何进行代码优化?
重复代码逻辑的抽象:保护成员函数
init:对象构造时的初始化操作
copy:在堆空间中申请新的内存,并执行拷贝操作
update:将指定的堆空间作为内部存储数组使用


小结:StaticArray通过封装原生数组的方式实现数组类,DynamicArray动态申请堆空间,使得数组长度动态可变,
数组对象能够代替原生数组,并且使用上更安全,代码优化是项目开发过程中不可或缺的环节。
*/
/***********************************************************************************************
#include <iostream>
#include "DynamicArray.h"
using namespace WSlib;
using namespace std;


int main()
{
DynamicArray <int> l(5);
for(int i=0;i<l.length();i++)
{
l[i]=i*i;
}
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
DynamicArray <int> s1(10);
s1=l;
//s1.resize(8);
s1.resize(3);
for(int i=0;i<s1.length();i++)
{
cout<<s1[i]<<endl;
}
//s1[4]=100;//越界抛异常

return 0;
}
************************************************************************************************/

猜你喜欢

转载自blog.csdn.net/ws857707645/article/details/80342030