之前说过C++中的类模板可以容纳任何类型的数据,那能否建立一个通用的组(类)使得也能够容纳任何类型的数组?
.直接访问的线性群体——数组类
.静态数组是具有固定元素个数的群体,其中的元素可以通过下标直接访问。
.缺点:大小正在编译时就已经确定,在运行时无法修改
.动态数组有一系列位置连续的,任意数量相同类型的元素组成
.优点:其元素个数可以在程序运行时改变
.动态数组类模板程序
#ifndef ARRAY_H
#define ARRAY_H
#include <cassert>//提供宏assert的定义。可以在程序中关键的地方使用这个宏来进行断言。如果一处断言被证明非真,我们希望程序在标准错误流输出一条适当的提示信息,并且使执行异常终止。
template<class T>//数组类模板定义
class Array
{
public:
Array(int sz = 50); //构造函数
Array(const Array<T>& a);//赋值构造函数
~Array(); //析构函数
//重载“=”
//如果一个函数的返回值是一个对象的值,就是右值,不能成为左值
//如果返回值为引用。由于引用是对象的别名,通过引用可以改变对象的值,因此是左值(我们希望能修改运算后的数组)
Array<T>& operator =(const Array<T>& rhs);
//重载“[]”
T& operator [](int i);
//重载“[]”常函数
const T& operator [](int i)const;
//重载到T*类型的转换
operator T* ();
operator const T* ()const;
int getSize()const; //取数组的大小
void resize(int sz); //修改数组的大小
private:
T* list; //用于存放动态分配的数组的内存首地址
int size; //数组大小(元素个数)
};
//构造函数
template <class T>
Array<T>::Array(int sz)
{
assert(sz >= 0); //sz为数组大小,应当为非负数
size = sz; //将元素个数赋值给变量size
list = new T[size];//动态分配size个T类型的元素空间
}
//复制构造函数
template <class T>
Array<T>::Array(const Array<T>& a)
{
//获取对象x的大小size,并赋值给当前对象的成员
size = a.size;
//动态分配n个T类型的元素空间
list = new T[size];
//从对象x复制元素到本对象
for (int i=0;i<size;i++)
{
list[i] = a.list[i];
}
}
//析构函数
template <class T>
Array<T>::~Array()
{
delete[] list;//new过申请的空间要靠delete释放
}
//重载“=”,将对象rhs赋值给本对象,实现对象之间的主体赋值
template <class T>
Array<T>& Array<T>::operator=(const Array<T>& rhs)
{
if(&rhs!=this)
{
//如果本对象中的数组大小与rhs的不同,则删除数组原有内存,然后重新分配
if(size!=rhs.size)
{
delete[] list; //删除数组原有的内存
size = rhs.size; //设置本对象的大小
list = new T[size];//重新分配size个T类型元素的内存
}
//从对象x复制数组元素到本对象
for(int i=0;i<size;i++)
{
list[i] = rhs.list[i];
}
}
//返回当前对象的引用
return *this;
}
//重载下标运算符,实现与普通数组一样通过下标访问元素,并具有越界检查功能
template <class T>
T& Array<T>::operator[](int i)
{
assert(n >= 0 && n < size);//检查下标是否越界
return list[n]; //返回下标为n的数组元素
}
template <class T>
const T& Array<T>::operator[](int i)const
{
assert(n >= 0 && n < size);//检查下标是否越界
return list[n]; //返回下标为n的数组元素
}
//重载指针转换运算符,将Array类的对象名转换为T类型的指针
//这样就可以接收赋值了
template <class T>
Array<T>::operator T*()
{
return list;//返回当前对象中私有数组的首地址
}
//取当前数组的大小
template <class T>
int Array<T>::getSize() const
{
return size;
}
//将数组大小修改为sz
//基于底层基于数组调整大小,这个时间空间开销很高
template <class T>
void Array<T>::resize(int sz)
{
//检查sz是否为非负
assert(sz >= 0);
//如果指定的大小与原有大小一样,则说明也不做
if(sz==size)
{
return;
}
T* newList = new T[sz]; //申请新的数组内存
int n = (sz < size) ? sz : size;//将sz与size中较小的一个赋值给n
//将原有数组中前n个元素复制到新数组中
for(int i=0;i<n;i++)
{
newList[i] = list[i];
}
delete[] list; //删除原数组
list = newList;//使list指向新的数组
size = sz; //更新size
}
#endif //ARRAY_H
应用例子:
int main()
{
//用来存放质数的数组,初始状态有10个元素
Array<int> a(10);
int n, count = 0;
cout << "Enter a value >= 2 as upper limit for prime numbers:";
cin >> n;
for(int i=2;i<n;i++)
{
//检查i是否能被比它小的质数整除
bool isPrime = true;
for(int j=0;j<count;j++)
{
//若i被a[j]整除,说明i不是质数
if(i%a[j]==0)
{
isPrime = false;
break;;
}
if(isPrime)
{
if(count==a.getSize())
{
a.resize((count * 2));
}
a[count++] = i;
}
}
}
for(int i=0;i<count;i++)
{
cout << setw(8) << a[i];
}
cout << endl;
return 0;
}