WUSTOJ 运算符重载 C++
一、前言
(1)自定义类型 = 自定义类型 存在,可手写的 赋值构造函数 却时有时无?
- 赋值构造函数属于6大默认成员函数,没有写编译器也是会重新生成
- 只要写的这个类在
构造的时候不需要动态开辟空间
来存储,之后就不需要深复制,也就不需要写深复制的赋值构造函数,系统会自动调用默认的浅赋值的值拷贝
赋值构造函数
(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;
}
完