非成员函数的操作符重载
在成员函数的操作符重载这篇中,我们掌握了成员函数重载操作符(如 +=),其核心思路是将左操作数作为调用者(this 指向它)。但这存在一个天然限制:左操作数必须是本类的对象。例如,当你希望写出 3.14 + c(double + complex)时,3.14 不是复数对象,编译器无法调用 complex 的成员函数。非成员函数(全局函数)重载 正是为了解决这类“左操作数非本类对象”的场景,也提供了更灵活的运算符匹配方式。
全局函数重载语法
核心概念:非成员函数(全局函数)重载操作符,函数名不带有类名前缀,所有操作数都显式写在参数列表中。
1 | // 成员函数:左操作数由 this 提供 |
易混淆点:成员函数重载二元操作符时,参数列表中只有一个参数(右操作数),左操作数由 this 提供;而非成员函数重载二元操作符时,参数列表中有两个参数(左右操作数各一个)。一元操作符:成员函数无参数,非成员函数有一个参数。
歧义风险:对于 a + b,编译器可能先查找成员函数再查找非成员函数。但 不能同时提供两个版本,否则会产生歧义。设计者只能二选一。
多种参数组合的匹配
问题:在数学中,复数可以与实数(double)直接相加,如 c + 5.0 或 5.0 + c。如果只写一个 operator+(complex, complex),那么 5.0 会被隐式转换为 complex(如果构造函数允许)。但对于 double + complex,左操作数 double 不是类对象,无法找到成员函数。因此,为了支持所有常见写法,需要显式提供多个版本的重载。
1 | // 示例代码:为复数类提供三种加法重载 |
编译器自动匹配:当用户写出 3.14 + c 时,编译器会查找参数类型为 (double, complex) 的 operator+,并调用对应的重载版本。
返回值的问题
核心问题:非成员函数中的二元操作符(如 +)通常需要创建一个新的对象来存放结果,而这个对象是函数内部的局部变量,绝不能返回引用,只能返回值的拷贝(return by value)。
C++ 中可以使用 typename(参数列表) 直接创建临时对象(无名称,生命周期到所在语句结束),非常适合用于函数返回值的构造。
临时对象语法:complex(3, 4) 创建一个无名复数对象。
RVO(返回值优化):编译器可省略临时对象的拷贝,直接构造到调用方。
因此,return complex(…) 是高效且安全的写法,不必担心性能问题。







