加号运算符重载必须是类成员或友元函数;若为全局函数,须声明为friend或至少一个参数为该类类型,否则编译失败;推荐用friend实现,返回新对象。

加号运算符重载必须是类成员或友元函数
直接在类外定义 operator+ 全局函数会编译失败,除非至少一个参数是该类类型且函数声明为 friend 或定义在类内。否则编译器无法匹配重载决议。
常见错误现象:error: no match for 'operator+' (operand types are 'MyClass' and 'MyClass'),往往是因为函数签名不匹配或未声明为友元。
- 推荐做法:把
operator+声明为friend函数,避免隐式转换被限制,也方便访问私有成员 - 若作为成员函数,左侧操作数固定为
*this,右侧是参数;作为友元,则两个参数都显式写出 - 返回值应是新对象(非引用),避免返回局部对象引用导致悬垂
class Vec {
int x_, y_;
public:
Vec(int x = 0, int y = 0) : x_(x), y_(y) {}
friend Vec operator+(const Vec& a, const Vec& b) {
return Vec(a.x_ + b.x_, a.y_ + b.y_);
}
};
输出运算符重载必须是全局友元函数
operator 不能是成员函数,因为左操作数是 <code>std::ostream&,而你无法修改 std::ostream 类来添加成员函数。唯一合法方式是定义为非成员、非模板的 friend 函数。
常见错误现象:error: 'operator,或者即使编译通过但输出为空——多半是忘了加 <code>friend 声明,导致无法访问私有成员。
立即学习“C++免费学习笔记(深入)”;
- 函数签名必须是
std::ostream& operator - 必须在类内加
friend声明,否则拿不到私有字段 - 记得最后返回
os,支持链式调用(如cout )
class Vec {
int x_, y_;
public:
Vec(int x = 0, int y = 0) : x_(x), y_(y) {}
friend Vec operator+(const Vec& a, const Vec& b);
friend std::ostream& operator<<(std::ostream& os, const Vec& v) {
os << "(" << v.x_ << ", " << v.y_ << ")";
return os;
}
};
const 正确性与参数传递方式直接影响安全性和效率
所有二元运算符重载的参数都应以 const T& 形式传入,尤其是当类含资源(如指针、容器)时。否则既可能意外修改实参,又触发不必要的拷贝。
容易踩的坑:用值传递(Vec a, Vec b)导致每次调用都构造临时对象;或漏写 const 导致无法绑定字面量/临时对象(如 Vec(1,2) + Vec(3,4) 失败)。
-
operator+的两个参数必须是const Vec& operator 的右参数也必须是 <code>const Vec&- 成员函数版本的
operator+还需在函数声明末尾加const(因不修改自身)
输出运算符重载后 cout
如果重载了 operator 却发现 <code>cout 报错或输出地址,大概率是函数没被找到——常见于命名空间隔离或遗漏 <code>#include <iostream></iostream>。
使用场景:类定义在自定义命名空间中时,operator 必须也在同一命名空间里,否则 ADL(参数依赖查找)找不到它。
- 不要把
operator 写在 <code>namespace std里(未定义行为) - 确保头文件中声明了
operator,且实现与声明在同一个命名空间 - 若用
using namespace xxx;,注意污染风险;更稳妥的是显式作用域调用或在对应命名空间内定义
复杂点往往不在语法本身,而在作用域和链接时机——比如头文件里只声明没实现,或实现放在 .cpp 里却没被链接,都会让重载“看起来没生效”。











