1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <cassert>
#include <iostream>
#include <stdexcept>
using namespace std;

#define size_a 10
#define size_b 20
#define add_size 10

// 数组类模板定义
template <class T>
class Array
{
private:
T *list; // T类型指针,用于存放动态分配的数组内存首地址
int size; // 数组大小(元素个数)
public:
Array(int sz = 50); // 构造函数
Array(const Array<T> &a); // 拷贝构造函数
~Array(); //析构函数
Array<T> &operator = (const Array<T> &rhs); // 重载"="使数组对象可以整体赋值
T &operator [] (int i); // 重载"[]",使Array对象可以起到C++普通数组的作用
const T &operator [] (int i) const; // "[]"运算符的const版本
operator T *(); // 重载到T*类型的转换,使Array对象可以起到C++普通数组的作用
operator const T *() const; // 到T*类型转换操作符的const版本
int getSize() const; // 取数组的大小
void resize(int sz); // 修改数组的大小
};

// 构造函数
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()
{
delete[] list;
}

// 拷贝构造函数
template <class T>
Array<T>::Array(const Array<T> &a)
{
// 从对象x取得数组大小,并赋值给当前对象的成员
size = a.size;
// 为对象申请内存并进行出错检查
list = new T[size]; // 动态分配n个T类型的元素空间
// 从对象X复制数组元素到本对象
for (int i = 0; i < size; i++)
list[i] = a.list[i];
}

// 重载"="运算符,将对象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]; // 重新分配n个元素的内存
}
// 从对象X复制数组元素到本对象
for (int i = 0; i < size; i++)
list[i] = rhs.list[i];
}
return *this; // 返回当前对象的引用
}

// 重载下标运算符,实现与普通数组一样通过下标访问元素,并且具有越界检查功能
template <class T>
T &Array<T>::operator [] (int i) throw(out_of_range)
{
if (i >= size)
throw out_of_range("Exception:out of range!");
return list[i];
}
template <class T>
const T &Array<T>::operator [] (int i) const throw(out_of_range)
{
if (i >= size)
throw out_of_range("Exception:out of range!");
return list[i];
}

// 重载指针转换运算符,将Array类的对象名转换为T类型的指针,
// 指向当前对象中的私有数组。
// 因而可以象使用普通数组首地址一样使用Array类的对象名
template <class T>
Array<T>::operator T *()
{
return list; // 返回当前对象中私有数组的首地址
}

template <class T>
Array<T>::operator const T *() const
{
return list; // 返回当前对象中私有数组的首地址
}

// 取当前数组的大小
template <class T>
int Array<T>::getSize() const
{
return size;
}

// 将数组大小修改为sz
template <class T>
void Array<T>::resize(int sz)
{
assert(sz >= 0); // 检查sz是否非负
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
}

int main()
{
Array<int> a(size_a);
Array<int> b(size_b);

cout << "数组a的大小为:" << a.getSize() << endl;
cout << "数组b的大小为:" << b.getSize() << endl;

try
{
for (int i = 0; i < size_a; ++i)
a[i] = i + 1;

b = a;
cout << "数组b的大小为:" << b.getSize() << endl;
cout << "数组b的内容为:";
for (int i = 0; i < b.getSize(); ++i)
cout << b[i] << ' ';
cout << endl;

b.resize(b.getSize() + add_size);
cout << "扩展数组b的容量后,其大小为:" << b.getSize() << endl;

// 测试异常捕获
cout << b[b.getSize()] << endl;
}
catch (out_of_range &e)
{
cout << e.what() << endl;
}
return 0;
}