运算符的重载,赋值重载,下标重载、对带默认参数的构造函数、析构函数、拷贝构造函数、重载赋值的赋值

//未完成
//运算符的重载,赋值重载,下标重载
//对带默认参数的构造函数、析构函数、拷贝构造函数、重载赋值的赋值
#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 必须显式调用
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值