WUSTOJ 运算符重载 C++

一、前言

(1)自定义类型 = 自定义类型 存在,可手写的 赋值构造函数 却时有时无?

  1. 赋值构造函数属于6大默认成员函数,没有写编译器也是会重新生成
  2. 只要写的这个类在构造的时候不需要动态开辟空间来存储,之后就不需要深复制,也就不需要写深复制的赋值构造函数,系统会自动调用默认的浅赋值的值拷贝赋值构造函数
    在这里插入图片描述

(2)自定义类型[ ] 存在,可手写的 [ ]运算符重载 却时有时无?

情况一
在这里插入图片描述
这里的 stu 相当于数组指针Student [ n ] 相当于一个结构体的数组,C语言中结构体数组使用的时候可以直接访问数组的下标。所以,这类题在写类的时候就不需要写 [ ] 的运算符重载

情况二
在这里插入图片描述
在这里插入图片描述
这里pARRAY是私有的,在类外不能用 a.pARRAY [ i ] 来访问数据。所以必须写 [ ] 的运算符重载


二、题目

(1)时间类

在这里插入图片描述

class Time
{
private:
	int hour;
	int minute;
	int second;
public:
	Time() :hour(1), minute(2), second(3)
	{}
	Time(int h,int m, int s):hour(h), minute(m), second(s)
	{}
	
	void Normalize();
	void Set(int h, int m, int s)
	{
		hour = h;
		minute = m;
		second = s;
		Normalize();
	}

	//n=t2-t1
	friend int operator-(const Time& t1, const Time& t2);
	//t2=t1+n
	friend Time operator+(const Time& t, int n);
	//t1=t1-n
	friend Time operator-(const Time& t, int n);
	//cout<<t1
	friend ostream& operator<<(ostream& out, const Time& t);
};

void Time::Normalize()
{
	//先保证各个位上非负,再考虑进位
	while (second < 0)
	{
		minute--;
		second += 60;
	}
	while (minute < 0)
	{
		hour--;
		minute += 60;
	}
	while (hour < 0)
		hour += 24;
	
	//second进位
	minute += second / 60;
	second %= 60;
	//minite进位
	hour += minute / 60;
	minute %= 60;
	//hour处理
	hour %= 24;
}

int operator-(const Time& t1, const Time& t2)
{
	int TotalSecond1 = t1.hour * 3600 + t1.minute * 60 + t1.second;
	int TotalSecond2 = t2.hour * 3600 + t2.minute * 60 + t2.second;
	return TotalSecond1 - TotalSecond2;
}

Time operator+(const Time& t, int n)
{
	Time tmp = t;
	tmp.second += n;
	tmp.Normalize();
	return tmp;
}

Time operator-(const Time& t, int n)
{
	Time tmp = t;
	tmp.second -= n;
	tmp.Normalize();
	return tmp;
}

ostream& operator<<(ostream& out, const Time& t)
{
	out << t.hour << ':' << t.minute << ':' << t.second;
	return out;
}

(2)日期类

在这里插入图片描述

class Date
{
private:
	int year, month, day;
	int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	bool isLeap(int y)
	{
		if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
		{
			days[2] = 29;
			return true;
		}
		days[2] = 28;
		return false;
	}
	//!!!整体考虑,就不用分年月日大小关系进退位计算
	int GetDate()
	{
		int k = 1, s = 0;
		while (k != month)
			s += days[k++];
		return s + day;
	}
public:
	Date():year(2023),month(5),day(20){}
	Date(int y, int m, int d):year(y), month(m), day(d){}
	
	void Set(int y, int m, int d)
	{
		year = y;
		month = m;
		day = d;
	}

	//n=d2-d1
	friend int operator-(Date& d1, Date& d2);
	//d2=d1+n
	friend Date operator+(Date& d, int n);
	//d1=d1-n
	friend Date operator-(Date& d, int n);
	//cout<<d1
	friend ostream& operator<<(ostream& out, const Date& d);
};

int operator-(Date& d1, Date& d2)
{
	d1.isLeap(d1.year);
	d2.isLeap(d2.year);
	int s = d1.GetDate() - d2.GetDate();
	
	int tmp = 0;
	Date d;
	for (int i = min(d1.year, d2.year); i < max(d1.year, d2.year); i++)
		tmp += d.isLeap(i) ? 366 : 365;
	if (d1.year < d2.year)
		s -= tmp;
	else
		s += tmp;
	
	return s;
}

Date operator+(Date& d, int n)
{
	int y = d.year;
	int k = d.isLeap(d.year) ? 366 : 365;
	int s = d.GetDate() + n;
	Date D;

	while (s > k)
	{
		s -= k;//要减的是这一年全年的天数
		y++;
		k = D.isLeap(y) ? 366 : 365;
	}
	int m = 0;
	for (int i = 1; i <= 12; i++)
	{
		if (s > D.days[i])
			s -= D.days[i];
		else
		{
			m = i;
			break;
		}
	}
	return Date(y, m, s);
}

Date operator-(Date& d, int n)
{
	int y = d.year;
	int k;
	int s = d.GetDate() - n;
	Date D;

	while (s <= 0)
	{
		y--;//要加的是上一年全年的天数
		k = D.isLeap(y) ? 366 : 365;
		s += k;
	}
	int m = 0;
	for (int i = 1; i <= 12; i++)
	{
		if (s > D.days[i])
			s -= D.days[i];
		else
		{
			m = i;
			break;
		}
	}
	return Date(y, m, s);
}

ostream& operator<<(ostream& out, const Date& d)
{
	out << d.year << '/' << d.month << '/' << d.day;
	return out;
}

(3)复数类

在这里插入图片描述

class Complex
{
private:
	double real;
	double imag;
public:
	Complex():real(0),imag(0){}
	Complex(double r, double i):real(r),imag(i){}

	void Set(double r, double i)
	{
		real = r;
		imag = i;
	}
	
	//c1+c2
	friend Complex operator+(Complex& c1, Complex& c2);
	//c1-c2
	friend Complex operator-(Complex& c1, Complex& c2);
	//c1*c2
	friend Complex operator*(Complex& c1, Complex& c2);
	//cout<<c1
	friend ostream& operator<<(ostream& out, const Complex& c);
};

Complex operator+(Complex& c1, Complex& c2)
{
	return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

Complex operator-(Complex& c1, Complex& c2)
{
	return Complex(c1.real - c2.real, c1.imag - c2.imag);
}

Complex operator*(Complex& c1, Complex& c2)
{
	return Complex(c1.real * c2.real - c1.imag * c2.imag, c1.imag * c2.real + c1.real * c2.imag);
}

ostream& operator<<(ostream& out, const Complex& c)
{
	if (c.imag > 0)//要手动加正号
	{
		if (c.imag == 1)
		{
			if (c.real == 0)
				out << 'i';
			else
				out << c.real << '+' << 'i';
		}
		else
		{
			if (c.real == 0)
				out << c.imag << 'i';
			else
				out << c.real << '+' << c.imag << 'i';
		}
	}
	else if (c.imag < 0)//负号是自带的,不需人为添加
	{
		if (c.imag == -1)
		{
			if (c.real == 0)
				out << '-' << 'i';
			else
				out << c.real << '-' << 'i';
		}
		else
		{
			if (c.real == 0)
				out << c.imag << 'i';
			else
				out << c.real << c.imag << 'i';
		}
	}
	else
		out << c.real;
	return out;
}

(4)学生类

在这里插入图片描述

class Student
{
private:
	int Id;
	char name[40];
	int score;
public:
	//cin>>stu[i]
    friend istream& operator>>(istream& in, Student& s);
    //<<stu[i]
    friend ostream& operator<<(ostream& out, const Student& s);
    //stu[j]>stu[j+1]
    friend bool operator>(const Student& s1, const Student& s2);
};

istream& operator>>(istream& in, Student& s)
{
    in >> s.Id >> s.name >> s.score;
    return in;
}

ostream& operator<<(ostream& out, const Student& s)
{
    out << "id=" << s.Id << ",name=" << s.name << ",score=" << s.score;
    return out;
}

bool operator>(const Student& s1, const Student& s2)
{
    if (s1.score != s2.score)
        return s1.score > s2.score;
    else
        return s1.Id > s2.Id;
}

(5)短整数类

在这里插入图片描述

class SmallInt
{
private:
	int val;
public:
	void Normalize()
	{
		while (val > 127)
			val -= 256;
		while (val < -128)
			val += 256;
	}
	SmallInt(int n = 0):val(n)
	{
		Normalize();
	}
	friend SmallInt operator+(const SmallInt& s1, const SmallInt& s2);
	friend SmallInt operator-(const SmallInt& s1, const SmallInt& s2);
	friend SmallInt operator*(const SmallInt& s1, const SmallInt& s2);
	friend SmallInt operator/(const SmallInt& s1, const SmallInt& s2);
	friend ostream& operator<<(ostream& out, SmallInt& s);
	friend istream& operator>>(istream& in, SmallInt& s);
};

SmallInt operator+(const SmallInt& s1, const SmallInt& s2)
{
	return SmallInt(s1.val + s2.val);
}

SmallInt operator-(const SmallInt& s1, const SmallInt& s2)
{
	return SmallInt(s1.val - s2.val);
}

SmallInt operator*(const SmallInt& s1, const SmallInt& s2)
{
	return SmallInt(s1.val * s2.val);
}

SmallInt operator/(const SmallInt& s1, const SmallInt& s2)
{
	if (s2.val != 0)
		return SmallInt(s1.val / s2.val);
	else
	{
		cerr << "Error:Division by zero." << endl;
		exit(1);
	}
}

ostream& operator<<(ostream& out, SmallInt& s)
{
	s.Normalize();
	out << s.val;
	return out;
}

istream& operator>>(istream& in, SmallInt& s)
{
	in >> s.val;
	return in;
}

(6)个人Person类

在这里插入图片描述

class Person
{
private:
	char name[40];
	int age;
public:
	Person() :age(0)
	{
		strcpy(name, "NULL");
	}
	//浅复制,不写系统也会默认生成,可以直接丢掉
	/*Person& operator=(const Person& p)
	{
		if (this != &p)
		{
			strcpy(name, p.name);
			age = p.age;
		}
		return *this;
	}*/
	
	int GetAge() const
	{
		return age;
	}

	friend Person operator+(const Person& p1, const Person& p2);
	friend istream& operator>>(istream& in, Person& p);
	friend ostream& operator<<(ostream& out, const Person& p);	
};

Person operator+(const Person& p1, const Person& p2)
{
	Person res;
	res.age = p1.age + p2.age;
	return res;
}

istream& operator>>(istream& in, Person& p)
{
	in >> p.name >> p.age;
	return in;
}

ostream& operator<<(ostream& out, const Person& p)
{
	out << "name=" << p.name << ",age=" << p.age;
	return out;
}

(7)分数类

在这里插入图片描述

#include <cmath>
class Fraction
{
private:
	int Numerator;
	int Denominate;
public:
	// 辅助函数:计算最大公约数
	int gcd(int a, int b)
	{
		return b == 0 ? a : gcd(b, a % b);
	}
	// 辅助函数:简化分数
	void simplify()
	{
		//分母只能是正整数
		if (Denominate < 0)
		{
			Numerator = -Numerator;
			Denominate = -Denominate;
		}
		//最简形式
		int div = gcd(fabs(Numerator), fabs(Denominate));
		if (div == 0)//!!!考虑分子为0的情况
		{
			Numerator = 0;
			Denominate = 0;
		}
		else
		{
			Numerator /= div;
			Denominate /= div;
		}
	}
	
	Fraction(int n = 0, int d = 1) :Numerator(n), Denominate(d)
	{
		simplify();
	}
	
	/*Fraction& operator=(const Fraction& f)
	{
		if (this != &f)
		{
			Numerator = f.Numerator;
			Denominate = f.Denominate;
		}
		return *this;
	}*/
	
	friend Fraction operator+(const Fraction& p1, const Fraction& p2);
	friend Fraction operator-(const Fraction& p1, const Fraction& p2);
	friend Fraction operator*(const Fraction& p1, const Fraction& p2);
	friend Fraction operator/(const Fraction& p1, const Fraction& p2);
	friend istream& operator>>(istream& in, Fraction& f);
	friend ostream& operator<<(ostream& out, Fraction& f);
};

Fraction operator+(const Fraction& p1, const Fraction& p2)
{
	Fraction res;
	res.Numerator = p1.Numerator * p2.Denominate + p2.Numerator * p1.Denominate;
	res.Denominate = p1.Denominate * p2.Denominate;
	res.simplify();
	return res;
}

Fraction operator-(const Fraction& p1, const Fraction& p2)
{
	Fraction res;
	res.Numerator = p1.Numerator * p2.Denominate - p2.Numerator * p1.Denominate;
	res.Denominate = p1.Denominate * p2.Denominate;
	res.simplify();
	return res;
}

Fraction operator*(const Fraction& p1, const Fraction& p2)
{
	Fraction res;
	res.Numerator = p1.Numerator * p2.Numerator;
	res.Denominate = p1.Denominate * p2.Denominate;
	res.simplify();
	return res;
}

Fraction operator/(const Fraction& p1, const Fraction& p2)
{
	Fraction res;
	res.Numerator = p1.Numerator * p2.Denominate;
	res.Denominate = p1.Denominate * p2.Numerator;
	res.simplify();
	return res;
}

istream& operator>>(istream& in, Fraction& f)
{
	in >> f.Numerator >> f.Denominate;
	f.simplify();
	return in;
}

ostream& operator<<(ostream& out, Fraction& f)
{
	f.simplify();
	out << f.Numerator << '/' << f.Denominate;
	return out;
}

(8)整型动态数组类

在这里插入图片描述

class ARRAY
{
private:
	int* pARRAY;
	int length;
public:
	ARRAY(int n) :length(n)
	{
		pARRAY = new int[n];
		for (int i = 0; i < n; i++)
			pARRAY[i] = 0;
	}
	~ARRAY()
	{
		delete[] pARRAY;
	}
	
	//a[i]
	int& operator[](int index) const//对象a是const的,只能调用const的成员函数
	{
		return pARRAY[index];
	}
	
	//*(a+j)
	//方法一:
	/*int* operator+(int index) const
	{
		return pARRAY + index;
	}*/
	//方法二:类型转换运算符
	//当这个类的一个对象需要被当作int*类型使用时,编译器会自动调用这个类型转换运算符
	operator int* () const
	{
		return pARRAY;
	}
	
	friend ostream& operator<<(ostream& out, const ARRAY& a);
};

ostream& operator<<(ostream& out, const ARRAY& a)
{
	out << "length=" << a.length << ",element={";
	for (int i = 0; i < a.length; i++)
	{
		//对象a是常引用,是const的,只能调用const的成员函数,所以
		//上面的int& operator[](int index)最后需要加const
		out << a[i];
		if (i < a.length - 1)
			out << ',';
	}
	out << '}';
	return out;
}

(9)矩形类

在这里插入图片描述

class Rectangle
{
private:
	double width;
	double height;
public:
	//
	double area() const
	{
		return width * height;
	}
	//r[j]>r[j+1]
	friend bool operator>(const Rectangle& r1, const Rectangle& r2);
	//cin>>r[i]
	friend istream& operator>>(istream& in, Rectangle& r);
	//<<r[i]
	friend ostream& operator<<(ostream& out, const Rectangle& r);
	
};

bool operator>(const Rectangle& r1, const Rectangle& r2)
{
	return r1.area() > r2.area();
}

istream& operator>>(istream& in, Rectangle& r)
{
	in >> r.width >> r.height;
	return in;
}

ostream& operator<<(ostream& out, const Rectangle& r)
{
	out << "width=" << fixed << setprecision(2) << r.width
		<< " height=" << fixed << setprecision(2) << r.height
		<< " area=" << fixed << setprecision(2) << r.area();
	return out;
}

(10)字符串String

在这里插入图片描述

class CSTRING
{
private:
	char* p;
public:
	//默认构造函数不会为 char* p 分配内存,因此在使用 p 之前需要手动分配内存
	//构造函数是动态开辟的,随之而来需要自己写可以深复制的复制构造函数,不能再用系统默认生成的浅赋复制的值拷贝默认赋值构造函数
	CSTRING(const char* str = "")
	{
		if (str)
		{
			p = new char[strlen(str) + 1];
			strcpy(p, str);
		}
		else
		{
			p = new char[1];
			p[0] = '\0';
		}
	}
	CSTRING(const CSTRING& s)
	{
		p = new char[strlen(s.p) + 1];
		strcpy(p, s.p);
	}
	~CSTRING()
	{
		delete[] p;
	}
	
	//t=cs[j]
	CSTRING& operator=(const CSTRING& s)
	{
		if (this != &s)
		{
			delete[] p;
			p = new char[strlen(s.p) + 1];
			strcpy(p, s.p);
		}
		return *this;
	}
	//cs[j]>cs[j+1]
	friend bool operator>(const CSTRING& s1, const CSTRING& s2);
	//cin>>cs[i]
	friend istream& operator>>(istream& in, CSTRING& s);
	//<<cs[i]
	friend ostream& operator<<(ostream& out, const CSTRING & s);
};

bool operator>(const CSTRING& s1, const CSTRING& s2)
{
	return strcmp(s1.p, s2.p) > 0;
}

istream& operator>>(istream& in, CSTRING& s)
{
	//目的是把数据写入s对象里面的指针中,但是要考虑之前已经开辟的空间大小会不会不够,
	//所以先把数组写到缓冲区,然后把原先空间释放,开新的足够大小的空间,再把数据放进去
	char buffer[1024];
	in >> buffer;
	
	delete[] s.p;
	s.p = new char[strlen(buffer) + 1];
	strcpy(s.p, buffer);
	
	return in;
}

ostream& operator<<(ostream& out, const CSTRING& s)
{
	out << s.p;
	return out;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值