//未完成
//运算符的重载,赋值重载,下标重载
//对带默认参数的构造函数、析构函数、拷贝构造函数、重载赋值的赋值
#include <iostream>
using namespace std;
//数组类
//以后T类型就是int类型
//这样定义的好处
//如果以后int改成其他数据类型就之用修改这一个地方
//但是typedef的用法却不怎么熟悉,需要复习
typedef int T;
class Array
{
T* data; //在堆里分配
int sz; //表示数据的个数
int max; //堆中的空间大小
//扩容函数
void expand()
{
max = 2*max;
//引入了新的数组,重新分配了空间
T* t = new T[max];
for (int i = 0; i < sz; i++)
{
t[i] = data[i];
}
//释放掉旧的数组的空间,指向新的数组
//必须使用delete[],
delete[] data;
data = t;
}
public:
//带默认参数的构造函数
//析构函数
//拷贝构造
//重载赋值
//explicit 构造函数不允许隐式的调用,如此就会怎样?Array a 这样构造应该不算隐式的调用吧?
explicit Array(int n = 1):max(n),sz(0) //初始化为0就直接在小括号里填0就OK
{
data = new T[n];
}
~Array()
{
//new的[] 就delete []
delete[] data;
}
//拷贝构造
Array(const Array& a)
{
max = a.max;
sz = a.sz;
data = new T[max];
for (int i = 0; i<sz; i++)
{
data[i] = data[i];
}
}
//重载赋值运算符
//这里的const加上好像没有什么影响,是么?
/*const*/ Array& operator=(const Array& a)
{
//是否自赋值?
if (this == &a)
{
return *this; //是哪个的this?赋值号左侧的还是右侧的?
}
//释放掉=左侧对象的旧空间,分配新空间给左侧对象
delete[] data;
data = new T[a.max];
//完成赋值,
max = a.max;
sz = a.sz;
for (int i = 0; i < sz; i++)
{
data[i] = data[i];
}
//是哪个this?赋值号左侧还是右侧的?
return *this;
}
//为什么返回引用呢?
//比如要对a[0]赋值,如果返回的是临时值,那么就无法作为左值
//a[0] = 1;
//这样的操作就无法成功
//=======================
//下标越界是否要检查?
//调用者应该负责
//如果效率至上,就不检查越界
T& operator[](int index)
{
return data[index];
}
//老师举的一个例子,不知道从哪里来的,函数检查下标越界
T& at(int index)
{
if (index < 0 || index >= sz) throw "out";
return data[index];
}
// T& operator[](int index)
// {
//
// }
T& operator[](char ch)
{
//曾经ch掉了一个h,因为没有试过重载中括号里可以使用字符,所以没有发现什么错误
return data[ch-'a']; //a算0,b算1,如此……
}
T& operator[](double d)
{
//可以四舍五入,道理是什么样的?
//转成int类型是要去掉小数点后面的
//如果d小于0.5,那么这个数转成int就没机会+1了
//如果d大于等于0.5,那么这个数转成int就会+1了
return data[(int)(d+0.5)];
}
bool insert(int index,const T& d)
{
//判断数组是否越界
//这里曾经是index>=sz
if (index<0 || index > sz)
{
return false;
}
//判断数组是否满了
if (sz == max)
{
expand();
}
data[index] = d;
//因为只插入一个,所以只用++
sz++;
return true;
}
bool push_back(const T& d)
{
return insert(sz,d); //是从0开始算的把,sz是sz+1个?
}
//重载<<,可以依次输出数组元素,元素间以空格分开
friend ostream& operator<<(ostream& o,const Array& a)
{
for (int i = 0; i < a.sz; i++)
{
o << a.data[i] << ' ';
}
return o;
}
int size()
{
return sz; //insert函数会监控sz,所以这里只管返回sz就ok了。
}
};
int main()
{
Array a;
a.insert(0,1);
a.insert(1,2);
a.push_back(3);
cout << "Array类的所有元素为:" << a << endl;
Array b = a;
Array c;//空参有了?默认值的构造?据说都带了默认值的构造函数相当于附加了一个空参的构造函数?
//如果写成Array c();这到底是初始化还是函数?
c = a; //是重载了赋值吧?感觉和拷贝构造蛮类似的,但是拷贝构造好要有新对象构造,这里的c和a都是已经存在的了。
//如果赋值重载时没有返回当前对象,这里是不可以进行左值操作的,因为是给一个临时变量赋值。
//且如果返回值类型的修饰符为const,那也不允许
//我记错了,没有上一句那回事
a[0] = 100; //a.operator[](0) = 100;
a[1] = 200; //a.operator[](1) = 200;
for (int i = 0; i< a.size(); i++)
{
cout << a[i] << ' ';
}
cout << endl;
a['a'] = 123; //a.operator[]('a') = 123;
a['b'] = 456;
a['c'] = 789;
cout << a << endl;
a[2.13] = 213;
a[0.8] = 8;
a[0.2] = 2;
cout << a << endl;
//explicit 必须显式调用
}
运算符的重载,赋值重载,下标重载、对带默认参数的构造函数、析构函数、拷贝构造函数、重载赋值的赋值
最新推荐文章于 2022-03-21 10:47:51 发布