跳转至

11 运算符重载⚓︎

569 个字 20 行代码 预计阅读时间 3 分钟

在类里,我们可以像声明函数一样声明运算符的功能,这样使用对象的运算符时就像执行一个自定义函数一样,覆盖了原来运算符的功能,类似函数重载。

我们可以重载以下运算符:

然而,以下运算符不能被重载:

  • 作用域限定符(scope resolution)::
  • 三目运算符 ?
  • 成员访问运算符 .
  • 指向成员的指针运算符 .*
  • 对象大小、类型、强制转换运算符:size()typeid()cast()

例子

student.h
class Student
{
    public:
        // ...
        bool operator < (const Student& rhs) const;
    private:
        // ...
}
student.c
#include "student.h"
// ...

bool operator < (const Student& rhs) const
{
    return age < rhs.age; // 这里的 age 就是 this->age
}

例如,我们已经定义了一个类,现在想要输出类的内容。但是根据经验,我们无法直接用 << 输出,这时需要用到运算符重载:

std::ostream operator << (std::ostream& out, const Time& time)
{
    out << time.hours << " : " << time.minutes << " : " << time.seconds;
    return out;
}

有两种重载运算符的方法:

  • 成员函数:在类的作用域内声明要重载的运算符,此时可以用 this->xxx 访问成员变量。但这种方法不适用于左侧对象未知的情况。
  • 非成员函数:在类的外面声明要重载的运算符,这样能够同时将左侧和右侧的对象作为参数定义。这种方法很适合用在 STL 上,因为它允许左侧是一个非类类型的变量(比如比较 doubleFraction,也允许将重载的运算符用于不是我们自己定义的类里(比如 vector 类型的 StudentList,上面我们没定义过

前一种方法允许运算符直接访问成员变量,但是后者无法直接访问,需要用到关键词 friend(友元,它允许非成员函数或者别的类来访问某个类的数据。

使用方法:

  • 非成员函数:在函数声明开头加上关键词 friend 即可,函数定义不用变
  • 类:在前面加一条语句:friend class <name>;

注意!

非成员运算符重载时需要留心一些特别的运算符,比如 newdelete,不要对这类运算符进行重载(它们可以被重载,这样的重载称为全局重载,否则会造成不良后果。

运算符重载の使用哲学

  • 重载后的运算符意义应该明确
  • 重载后的运算符的功能应该与它原有功能类似(不要干出把 + 重载为减法的蠢事
  • 若意义不明确,需给它一个常见的名字

评论区

如果大家有什么问题或想法,欢迎在下方留言~