1.概念
运算符重载是一种使对象操作更加美观的技术,可以将运算符重载理解为语法糖。运算符重载将函数重载的概念扩展到运算符上,赋予C++运算符更多含义。例如,将*用于地址,可获取这个地址中的值,将*用于两个数字,可获取两个数字的乘积
C++可将运算符重载扩展到用户定义的类型,例如,允许使用+将两个对象相加,编译器根据操作数的数目和类型决定使用哪种加法定义,运算符重载使代码更加自然、容易理解
要重载运算符,需使用被称为运算符函数的特殊函数形式,格式:operatorop(argument-list)
2.例子
两个非基本类型对象相加,比如两个时间类对象(由小时、分钟组成),可以在自定义时间类Time中添加两种形式表示相加的函数,分别为
1)Time add(const Time& t) const;
2)Time operator+(const Time& t) const;
mytime.h
#ifndef MYTIME_H
#define MYTIME_H
class Time {
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m);
void AddMin(int m);
void AddHr(int h);
void Reset(int h = 0, int m = 0);
Time add(const Time& t) const;
Time operator+(const Time& t) const;
void Show() const;
};
#endif
mytime.cpp
#include <iostream>
#include "mytime.h"
Time::Time() {
hours = 0;
minutes = 0;
}
Time::Time(int h, int m) {
hours = h;
minutes = m;
}
void Time::AddMin(int m) {
minutes += m;
hours += minutes / 60;
minutes %= 60;
}
void Time::AddHr(int h) {
hours += h;
}
void Time::Reset(int h, int m) {
hours = h;
minutes = m;
}
Time Time::add(const Time& t) const {
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
Time Time::operator+(const Time& t) const {
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
void Time::Show() const {
std::cout << hours << " hours, " << minutes << " minutes" << std::endl;
}
usetime.cpp
#include <iostream>
#include "mytime.h"
using namespace std;
int main() {
Time coding(2, 40);
Time fixing1(5, 55);
Time total;
cout<< "coding time = ";
coding.Show();
cout << endl;
cout << "fixing1 time = ";
fixing1.Show();
cout << endl;
total = coding.add(fixing1);
cout << "After the first fixing, total time = ";
total.Show();
cout << endl;
Time fixing2(1, 10);
cout << "fixing2 time = ";
fixing2.Show();
cout << endl;
total = total.operator+(fixing2);
cout << "After the second fixing, total time = ";
total.Show();
cout << endl;
Time fixing3(3, 28);
cout << "fixing3 time = ";
fixing3.Show();
cout << endl;
total = total + fixing3;
cout << "After the third fixing, total time = ";
total.Show();
cout << endl;
return 0;
}
coding、fixing1、fixing2、fixing3均是Timg类的对象,两个Time对象相加有3种形式
1)total = coding.add(fixing1);
2)total = total.operator+(fixing2);
3)total = total + fixing3;
显然,第3种方式使代码更加简洁,便于Time类的调用者使用()
3.通过友元实现运算符重载
实现运算符重载需要友元的原因:在为类重载二元运算符(带两个参数的运算符)有时需要友元,“实数乘以Time对象”就属于这种情况,重载的乘法运算符和重载的加法运算符的区别在于,重载的加法运算符结合两个Time对象,重载的乘法运算符将一个Time值与一个double值结合在一起,而这个区别限制了重载的乘法运算符的使用方式
Time A;
Time B;
A = B * 2.75; // 左侧的操作数是调用对象
将会被转换为下面的函数调用
A = B.operator*(2.75);
但是,“A = 2.75 * B”无法调用B::operator*函数,因为2.75不是Time对象
可以在Time类中创建友元函数解决这个问题(2.75不是Time对象,所以无法创建Time类成员函数来解决这个问题,但是待创建的函数必须能够访问Time对象的成员变量,所以在此使用友元函数),在mytime.h中添加重载的乘法运算符的声明
Time operator*(double n) const; // for A = B * 2.75
friend Time operator*(double n, const Time& t); // for A = 2.75 * B
在mytime.cpp中添加重载的乘法运算符的定义
Time Time::operator*(double n) const {
Time result;
long totalminutes = hours * n * 60 + minutes * n;
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
Time operator*(double n, const Time& t) {
Time result;
long totalminutes = t.hours * n * 60 + t.minutes * n;
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
在上例中,两个重载的乘法运算符函数逻辑是相同的,所以在mytime.cpp省略“friend Time operator*(double n, const Time& t);”的定义,将mytime.h改为
Time operator*(double n) const; // for A = B * 2.75
friend Time operator*(double n, const Time& t) {
return t * n;
} // for A = 2.75 * B
4.重载<<运算符
可以对<<运算符重载,使之能与cout一起来显示对象的内容
在mytime.h中添加友元函数的声明
friend ostream& operator<<(ostream& os, const Time& t);
在mytime.cpp中添加友元函数的定义
ostream& operator<<(ostream& os, const Time& t) {
os << t.hours << " hours, " << t.minutes << " minutes";
return os;
}
注:新的Time类声明使operator<<()函数成为Time类的一个友元函数。但该函数不是ostream类的友元。operator<<()函数接受一个ostream参数和一个Time参数,因此表面看起来它必须同时是这两个类的友元。然而,尽管该函数访问了Time对象的各个成员,但只将ostream对象做为一个整体使用。因为operator<<()直接访问Time对象的私有成员,所以它必须是Time类的友元。但由于它并不直接访问ostream对象的私有成员,所以并不一定必须是ostream类的友元,所以不必修改ostream的定义
参考资料:
1.C++ Primer Plus(第6版)中文版