“重载”定义
c++语法中有基本的运算符,例如+、-、<<等。但他们使用的对象一般都是常规变量,例如int、float这样的类型。
如果我们希望将两个类相加(例如目的可能是将类的某些private值相加,并形成一个新的类),这时候我们就无法使用+来进行,因此我们需要重载运算符,使得运算符根据操作数的类型来选择运算逻辑。
重载使用实例
下面我们给出一个类定义:
class Time {
private:
int hour;
int minute;
int second;
public:
Time(int h = 0, int m = 0) {
hour = h;
minute = m;
}
~Time() {}
Time operator+(const Time& t) const {
Time sum;
sum.mintue = minute + t.minute;
sum.hour = (hour + t.hour + sum.minute / 60) % 24;
sum.minute = sum.minute % 60;
return sum.minute;
}
};
此时我们就对”+”运算符进行了重载,使得它可以对两个Time类对象进行相加操作。
重载使用的基本模式如下:
类名 operator符号(const 类名& 参数名) const {
// 重载逻辑
}
其中,类名是操作符所作用的类名,符号是重载的运算符,参数名是操作符所需要的另一个类名。
重载运算符有两种使用方式
一种是将其当成成员变量使用
另一种是将其当成”+”运算符使用
Time t1(10, 30);
Time t2(15, 45);
Time t3 = ti.operator+(t2);
Time t4 = t1 + t2; // 等价于t3
注意,当使用t1+t2时,t1是调用对象,而t2是传递的参数。
因为返回的值是Time,所以我们可以连用+运算符。
Time t5 = t1 + t2 + t3;
这个语句的转化流程为
Time t5 = t1.operator+(t2+t3);
->
Time t5 = (t1.operator+(t2.operator+(t3)));
// 因此是可行的
友元函数
让我们考虑一种重载,假设我们重载了*运算符,使得它可以对两个Time类对象进行相乘操作。
这里我们先不考虑这个返回值的意义。
Time operator*(int n, int m) const {
Time product;
product.hour = hour * n;
product.minute = minute * m;
return product;
}
我们可以这样使用这个重载
Time t1(10, 30);
Time t2 = t1 * 2; // 等价于t1.operator*(2)
但是,如果我们交换乘法顺序,会怎么样呢?
Time t3 = 2 * t1; // ???我们说过*左边是调用对象,但此时左边是2,显然不符合规则。
这时候,我们就需要考虑到友元函数的概念。
我们将新定义一个友元重载函数,将Time和int类都当作参数,传出新的Time对象。
之所以不使用普通的函数,是因为普通函数无法访问类的私有成员。
所以我们需要一个类的“友好”的函数,可以让他访问类的私有成员。
// 友元函数的声明需要放在类的声明内
friend Time operator*(const Time& t, int n);
// 定义时不需要friend关键字,也不需要定义域Time::
Time operator*(const Time& t, int n) {
Time product;
product.hour = t.hour * n;
product.minute = t.minute * n;
return product;
}
友元函数在使用时,会自动将前后的两个类当作参数,并调用友元函数。
t12 -> operator(t1, 2);
常见友元函数
我们还可以对<<运算符进行重载,使得它可以输出Time类的对象。
friend ostream& operator<<(ostream& os, const Time& t) {
os << t.hour << ":" << t.minute;
return os;
}
下面对代码进行解释。
一般我们使用的cout语句,cout其实是ostream类的一个对象,<<是一个被其重载的运算符,后面的变量或常量就是参数。
因此cout << x 的本质就是调用了x的operator<<函数,而函数实现就是打印变量的值。
之所以返回ostream&,是为了连用<<运算符。
Time t1(10, 30);
cout << t1; // 输出10:30
Time t2(15, 45);
cout << t1 << t2; // 输出10:3015:45
// cout << t1返回还是cout, 所以可以继续cout << t2
对于<<的重载,我们必须使用友元函数,不然的话,这个运算符的使用就会很奇怪
t1 << cout -> ti.operator<<(cout)
因此我们使用友元函数。