#ifndef _HEAP_ARRAY_H_

#define _HEAP_ARRAY_H_

/*

* why

* 2016/9/5 15:18

* 实现了一个较完善的数组类模板,在堆空间上

*/

template

< typename T >

class Heap_Array

{

private:

T *m_array;

int array_len;

Heap_Array(int len);//构造函数 设置一个数组的长度,并且将数组元素值全清0

// Heap_Array(const Heap_Array& obj); //因为我们类中,有成员使用了系统资源,所以需要我们自己提供一个深拷贝构造函数,不能用默认的浅

bool construct(int len); //第二阶段的构造过程

public:

bool set_array_val(int index, T set_val);//设置数组每个成员的值的成员函数,第一个是索引,第二个参数是设置值

bool get_array_val(int index, T& val); //得到数组index的值,用引用将值导出

int get_array_len(void);

//void free(void); //这样不好,有时会忘记调用

~Heap_Array(void); //所以提供了一个析构函数,用来对象销毁时清理对象申请的系统资源的

static Heap_Array* NewHeapArray(int len); //创建对象的函数。

T& operator [] (int index);

T operator [] (int index) const; //以便const的数组类对象使用这个[]重载,const的对象,只能使用const的成员函数。

Heap_Array& self(); //用来返回自身对象的。一遍与省去一些指针的操作

Heap_Array& operator = (const Heap_Array& obj); //提供一个深拷贝的赋值操作符重载函数

};


template

< typename T >

//设置数组的长度,是一个构造函数带参数的,对象定义的时候需要参数

Heap_Array<T>::Heap_Array(int len) : m_array(0)

{

array_len = len; //将数组的长度保存在array_len这个类成员变量中

}


template

< typename T >

Heap_Array<T>* Heap_Array<T>::NewHeapArray(int len) //创建一个对象的函数

{

Heap_Array* ret = 0; 

ret = new Heap_Array(len); //堆空间申请对象,同时Heap_Array(int len)构造函数也会执行

if ( !(ret && ret->construct(len)) ) //如果在堆空间申请申请对象失败或者第二阶段的构造过程在申请系统资源时异常失败

{

delete ret; //直接删除这个对象

ret = 0;

}


return ret; //返回这个对象的指针

}


template

< typename T >

bool Heap_Array<T>::construct(int len) //第二阶段的构造过程,用于处理申请资源相关的

{

m_array = new T[len]; //先向堆内存你申请len个T大小的内存空间,让指针m_array指向,就是一个T型数组

if (0 == m_array) //如果堆空间内存申请失败

{

return false; //返回false

}

else

{

/*这部分省略,因为类型是不确定的,所以我们也不知道开始给内存里面清零是否正确

for (int i=0; i<get_array_len(); i++) //否则成功,将申请到的堆空间中的内容清0

{

m_array[i] = 0; //将申请到的len个T大小的内存空间中的每个T类型大小的空间都赋值为0;

}

*/

return true;

}

}


//获取数组的长度

template

< typename T >

int Heap_Array<T>::get_array_len(void) //表明这个函数是在Heap_Array类中的,属于这个类的类作用域范围,只能用类的对象访问,前提是public

{

return array_len;

}


/*//太麻烦了,不用了,如果用的话,好要考虑对象拷贝时内存申请的失败,如果需要自己在完善吧

//自己提供一个深拷贝构造函数,因为我们的类成员有使用了系统资源,不能用编译器默认提供的浅拷贝,不然会引起错误

template

< typename T >

Heap_Array::Heap_Array(const Heap_Array& obj)

{

array_len = obj.array_len; //拷贝代表数组长度的成员变量的值

m_array = new T[obj.array_len]; //在次向系统堆空间申请内存,达到深拷贝的效果

for (int i=0; i<obj.array_len; i++)

{

m_array[i] = obj.m_array[i]; //拷贝数组每个元素的值

}

}

*/



template

< typename T >

//设置数组每个成员的值的成员函数,第一个是索引,第二个参数是设置值

bool Heap_Array<T>::set_array_val(int index, T set_val)

{

bool ret = (0 <= index) && (index < array_len); //看要设置的数组元素,是否越界了数组,是否在数组的长度范围

if (ret) //如果为true

{

m_array[index] = set_val;

}

return ret; //否则肯定返回的是falsh,正确返回true

}


template

< typename T >

//获取数组第index元素的值

bool Heap_Array<T>::get_array_val(int index, T& val)

{

bool ret = (0 <= index) && (index < array_len);

if (ret)

{

val = m_array[index];

}

return ret;

}


template

< typename T >

//释放申请的堆内存

Heap_Array<T>::~Heap_Array() //测试成功

{

//printf("kill sucess.\n");

delete[] m_array;

}


template

< typename T >

T& Heap_Array<T>::operator [] (int index)

{

return m_array[index];

}


template

< typename T >

T Heap_Array<T>::operator [] (int index) const //给const的数组对象使用的

{

return m_array[index];

}


template

< typename T >

Heap_Array<T>& Heap_Array<T>::self() //返回当前对象,为了后续省略指针的操作,为了展现到客户那没有指针操作

{

return *this;

}


template

< typename T >

Heap_Array<T>& Heap_Array<T>::operator = (const Heap_Array& obj) //赋值操作符重载,两种情况,1、自己给自己赋值。2、其他这个类对象给自己赋值

{

if (this != &obj) //如果不是自己给自己赋值的操作

{

T *point = 0;

point = new T[obj.array_len]; //重新申请堆空间

for (int i=0; i<obj.array_len; i++)

{

point[i] = obj.m_array[i]; //将新申请的堆空间中填上要赋的值。

}

array_len = obj.array_len;

delete m_array; //将原先的堆空间销毁

m_array = point; //成员指向新的堆空间

}

return *this; //如果是自己给自己赋值的操作,就直接返回当前的对象

}


#endif