为什么要使用运算符重载?
我们已经习惯用“+”来对整数、单精度和双精度进行加法运算。之所以可以对不同类型的数据进行操作,因为C++已经对“+”进行了重载。但是实际上很多用户定义的类型(比如类),也需要类似的操作。
class Money
{
public:
Money(int y = 0, int j = 0, int f = 0);
Money operator+(Money &);
void Show();
private:
int yuan, jiao, fen;
void Optimize();//优化函数
};
Money::Money(int y, int j, int f)
{
yuan = y;
jiao = j;
fen = f;
Optimize();
}
void Money::Optimize()
{
if (fen >= 10)
{
jiao++;
fen = fen - 10;
}
if (jiao >= 10)
{
yuan++;
jiao = jiao - 10;
}
}
Money Money::operator+(Money &m)
{
return Money(yuan + m.yuan, jiao + m.jiao, fen + m.fen);
}
void Money::Show()
{
cout << yuan << "." << jiao << "." << fen << endl;
}
int main()
{
Money cost1(300, 5, 6), cost2(105, 6, 7), total;
total = cost1 + cost2;
total.Show();
}
可以看出重载了“+”之后,Money类对象的加法书写形式变得十分简单。
C++语言中运算符重载的规则:
1. C++不允许用户自己定义新的运算符,只能对C++语言中已有的运算符进行重载。
2. 运算符重载针对新类型数据的实际需要,一般来说应该和原有功能类似。
3. 不能改变运算符操作个数;不能改变运算符原有优先级;不能改变运算符原有结合性;不能改变运算符原有语法结构。
如果在使用重载运算符时运算符左侧的操作数不是该类的对象,是C++的标准类型或是其它类的对象,则运算符重载函数就不能重载为该类的成员函数,但是可以将运算符重载为该类的友元函数。例如
friend Rational operator+(int i,Rational a);
class Point
{
public:
Point();
Point(int vx, int vy);
Point & operator++();//前置自增
Point operator++(int);//后置自增
friend Point & operator--(Point &p);//前置自减的友元函数
friend Point operator--(Point &p, int);//后置自减的友元函数
void Display();
private:
int x, y;
};
Point::Point()
{
x = 0;
y = 0;
}
Point::Point(int x, int y)
{
this->x = x;
this->y = y;
}
void Point::Display()
{
cout << "(" << x << "," << y << ")" << endl;
}
Point & Point::operator++()
{
if (x < 1000)
x++;
if (y < 1000)
y++;
return *this;
}
Point Point::operator++(int)
{
Point temp(*this);
if (x < 1000)
x++;
if (y < 1000)
y++;
return temp;
}
Point & operator--(Point &p)//这是个友元函数,所以不能Point &Point::operator(Point &p)
{
if (p.x>0)
p.x--;
if (p.y > 0)
p.y--;
return p;
}
Point operator--(Point &p, int)
{
Point temp(p);
if (p.x > 0)
p.x--;
if (p.y > 0)
p.y--;
return temp;
}
int main()
{
Point p1(10, 10), p2(150, 150), p3(20, 20), p4(160, 160), p5;
cout << "p1=";
p1.Display();
++p1;
cout << "++p1=";
p1.Display();
cout << "p3=";
p3.Display();
p5 = p3++;
cout << "p3++=";
p3.Display();
cout << "p2=";
p2.Display();
--p2;
cout << "--p2=";
p2.Display();
cout << "p4=";
p4.Display();
p5 = p4--;
cout << "p4--";
p4.Display();
cout << "p5=p4--";
p5.Display();
return 0;
}
C++语法规定,前置单目运算符没有形参重载为类的成员函数时没有形参,而后置单目运算符重载为类的成员函数时需要一个int型形参。这个int形参在函数中并不使用,纯粹是用来区别前置和后置,因此参数表中可以只给出类型,无需参数名。
注意:后置自增(自减)运算符按值返回Point对象,而前置自增(自减)运算符按引用返回Point对象。这是因为在进行自增(自减)前,后置自增(自减)运算符时先返回一个包含对象原始值得临时对象。C++将这样的对象作为右值处理,使其不能用在赋值运算符的左侧。前置的自增(自减)运算符返回实际自增(自减)后具有新值的对象,这种对象在连续的表达式中可以作为左值使用。