C++ 运算符重载(Operator Overloading)
运算符重载写法
类似与定义函数一样,只是把函数名变成operator 运算符。
例:
Time operator*(double mult, const Time & t) {
    Time result;
    long totalminutes = t.hours * mult * 60 + t.minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}1. 类中运算符重载
通过在类中定义成员函数实现:
class Time{
private:
    int hours;
    int minutes;
public:
    Time(){hours = 0, minutes = 0;};
    Time(int h, int m = 0): hours(h), minutes(m){};
    Time operator*(double mult) const; // 别忘加 const
    void show() const {cout << hours << ":" << minutes << endl;};
};
Time Time::operator*(double mult) const{
    Time result;
    long totalminutes = hours * mult * 60 + minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}上面程序中实现的运算符重载,可以做如下使用:
Time A(1, 2);
Time B = A * 2;
B.show()// 2:4注意:以上不可以写成: B = 2 * A;,这样写是错误的,无法通过编译。
因为B = A * 2;被编译器转换成了成员函数调用:B = A.operator*(2);而B = 2 * A中的2不是对象,编译器无法使用类成员函数进行转换。如果要解决以上出现问题,就要使用接下要介绍的友元函数重载。
2. 友元函数重载
通过在类中声明Time operator*(double mult, const Time &t)是友元函数:
注意:
- 虽然
operator*()在类中声明了,但它不是成员函数,因此不能使用成员函数运算符调用。- 虽然
operator*()不是成员函数,但是它与成员函数的访问权限相同。
class Time{
private:
    int hours;
    int minutes;
public:
    Time(){hours = 0, minutes = 0;};
    Time(int h, int m = 0): hours(h), minutes(m){};
    friend Time operator*(double mult, const Time &t);
    void show() const {cout << hours << ":" << minutes << endl;};
};
Time operator*(double mult, const Time & t) {
    Time result;
    long totalminutes = t.hours * mult * 60 + t.minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}上面程序中实现的运算符重载,可以做如下使用:
Time A(1, 2);
Time B = 2 * A;
B.show(); //2:4注意:以上不可以写成: B = A * 2;,这样也不行。如果既要用B = A * 2和B = 2 * A,可以把类中运算符重载和友元重载结合使用。
因为B = 2 * A;被编译器转换成了:B = operator*(2, A), 从而调用刚刚定义的非成员友元函数。
B = A * 2和B = 2 * A一起使用:
#include <iostream>
using namespace std;
class Time{
private:
    int hours;
    int minutes;
public:
    Time(){hours = 0, minutes = 0;};
    Time(int h, int m = 0): hours(h), minutes(m){};
    friend Time operator*(double mult, const Time &t);
    Time operator*(double mult) const;
    void show() const {cout << hours << ":" << minutes << endl;};
};
Time Time::operator*(double mult) const{
    Time result;
    long totalminutes = hours * mult * 60 + minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}
Time operator*(double mult, const Time & t) {
    Time result;
    long totalminutes = t.hours * mult * 60 + t.minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}
int main() {
    Time A(1, 2);
    Time B = 2 * A;
    B.show(); // 2:4
    Time C = A * 3;
    C.show(); // 3:6
    return 0;
}重载 << 运算符
第1种方法
friend void operator<<(ostream &os, const Time &t); // 先在类中声明;
void operator<<(ostream &os, const Time &t) {
    os << t.hours << " hours, " << t.minutes << " minutes";
}
// 使用
trip(4, 23);
cout << trip;// 4 hours, 23 minutes注意:通过这种重载方法之后,cout << 不能像平时那样正常使用了,比如cout << trip << "test1234" << endl这样写就会报错。接下来介绍第2种方法来解决此问题。
第2种方法
friend ostream& operator<<(ostream &os, const Time &t); // 先在类中声明;
ostream& operator<<(ostream &os, const Time &t) {
    os << t.hours << " hours, " << t.minutes << " minutes\n";
    return os;
}
// 使用
trip(4, 23);
cout << trip << " test1234" << endl;// 4 hours, 23 minutes test1234附——友元声明
1. 友元函数
class A{
private:
    int n;
public:
    friend void test(int x, A &a);
};
void test(int x, A &a) {
    a.n = x;
    cout << "num: " << a.n << endl;
}2. 友元类
class A{
private:
    int n;
public:
    friend class B;
};
class B{
private:
    int t;
public:
    void test(int x, A &a) {
        a.n = x;
        cout << "num: " << a.n << endl;
    }
};3. 友元类成员函数
class A; // 要先定义class A
class B{
private:
    int t;
public:
    void test(int x, A &a); // 在外部实现,不能在内部实现
};
class A{
private:
    int n;
public:
    friend void B::test(int x, A &a);
};
void B::test(int x, A &a) {
    a.n = x;
    cout << "num: " << a.n << endl;
}