C++中哪些运算符应定义为成员、友元或非成员函数?
C++ 运算符重载问题解答
1. 无operator+=场景下,operator+是否需要声明为友元?
- 二者没有直接关联,
operator+是否需要声明为友元的唯一判断标准是:它是否需要访问类的私有/保护成员。 - 常规实现中我们会用公有成员
operator+=来实现非成员operator+:先拷贝左操作数,再调用拷贝对象的operator+=后返回结果,这种场景下operator+不需要访问私有成员,自然不需要声明为友元。 - 若没有实现
operator+=,分两种情况处理:- 如果类提供了公有的getter接口,可以拿到运算需要的所有内部状态,直接在非成员
operator+中通过getter取值计算即可,不需要友元。 - 如果没有对应公有接口,
operator+需要直接访问类私有成员,就需要将其声明为类的友元。
示例代码:
- 如果类提供了公有的getter接口,可以拿到运算需要的所有内部状态,直接在非成员
class Rational { int num, den; public: Rational(int n, int d) : num(n), den(d) {} // 提供公有getter,operator+无需声明为友元 int numerator() const { return num; } int denominator() const { return den; } }; // 非成员operator+,通过公有接口访问内部状态即可完成运算 Rational operator+(const Rational& a, const Rational& b) { return Rational( a.numerator() * b.denominator() + b.numerator() * a.denominator(), a.denominator() * b.denominator() ); }
如果移除上面的两个getter接口,就需要把operator+声明为Rational的友元才能访问私有成员num和den。
2. <、>、>=、<=是否属于要定义为非成员的对称运算符?
- 这里提到的对称指的是运算符两侧操作数支持对称的隐式类型转换,和运算逻辑上
A op B是否等价于B op A无关,因此<、>、>=、<=也属于这类需要优先定义为非成员的运算符。 - 举个实际场景:如果你的类支持隐式构造(比如
Rational类有非explicit的Rational(int)构造函数),要让r < 1和1 < r都能正常编译,就必须把<定义为非成员函数:如果定义为成员函数,1 < r中字面量1无法被转换为类的this指针,会编译失败。 - 这类比较运算符是否需要声明为友元的判断逻辑和上文一致:如果可以通过公有接口完成比较逻辑,就不需要友元,否则需要声明为友元。
- 补充:C++20标准引入了三路比较运算符
operator<=>,仅需要默认实现该运算符,编译器就会自动生成所有比较运算符,不需要手动逐一实现。
内容的提问来源于stack exchange,提问作者Raea6789
相关产品推荐
相关产品推荐

