我目前正在创建一个将在其中重载运算符的实用程序类。使它们成为成员或非成员(friend
)职能的利弊是什么?或者它是否重要?也许这是最好的做法?
答案 0 :(得分:20)
我将使用“C ++编码标准:101规则,指南和最佳实践”:如果您可以将其作为非成员函数执行,则将其作为非成员函数(在同一名称空间中)执行。
其中一个原因:隐式类型转换效果更好。示例:您有一个带有重载运算符*的复杂类。如果要编写2.0 * aComplexNumber,则需要运算符*为非成员函数。
另一个原因:耦合较少。非成员函数与成员函数的耦合程度较低。这几乎总是一件好事。
答案 1 :(得分:16)
每个运营商都有自己的考虑因素。例如,<< operator(当用于流输出,而不是位移)时会将ostream作为其第一个参数,因此它不能成为您的类的成员。如果您正在实施加法运算符,您可能希望从双方的自动类型转换中受益,因此您也将使用非成员等等...
至于允许通过继承进行特化,一个常见的模式是根据虚拟成员函数实现非成员运算符(例如,运算符<<<对正在传递的对象调用虚函数print())。
答案 2 :(得分:4)
如果您计划实施流媒体运营商(<<>>),那么它们将是非会员方法,因为您的对象位于运营商的左侧。
如果您计划实施 - >,>()或[],它们自然是成员方法。
对于其他人(比较和数学),您应该查看Boost.Operators,这确实有帮助。
例如,如果要实现以下运算符:
MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);
你只需写:
class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
MyClass& operator+=(int);
private:
};
2 operator+
将自动生成为非会员,可让您从自动转化中受益。它们将在operator+=
期间有效实施,因此您只需编写一次代码。
答案 3 :(得分:3)
如果你正在实现op,那么很可能你需要实现op =。即如果你正在重载+运算符,那么你应该实现+ =。 如果您正在进行后增量或重载+运算符,请确保将const返回到对象。 因此,如果重载operator +,则将其实现为非成员运算符,并在其中使用+ =运算符。例如。
const A operator+(const A& lhs, const A& rhs)
{
A ret(lhs);
ret += rhs;
return ret;
}
答案 4 :(得分:2)
对于二元运算符,成员函数的一个限制是左对象必须是您的类类型。这可以限制使用操作员对称。
考虑一个简单的字符串类:
class str
{
public:
str(const char *);
str(const str &other);
};
如果将operator +作为成员函数实现,而str("1") + "2"
将编译,"1" + str("2")
将无法编译。
但是如果你将operator +作为非成员函数实现,那么这两个语句都是合法的。
答案 5 :(得分:0)
没有什么比最佳做法更好,但这取决于您正在超载的运营商..
例如
&gt;&gt; 和&lt;&lt; 不能作为成员函数重载。
假设你想这样做: obj1 = 2 * obj2 然后选择非会员功能。
对于二元运算符重载成员函数只需要1个参数(调用对象被非常传递),而非成员函数则需要2个参数。