我目前正在创建一个实用程序类,其中包含重载运算符。friend
将它们设为成员或非成员 ( ) 函数的优缺点是什么?还是根本不重要?也许有一个最佳实践?
6 回答
我会选择“C++ 编码标准:101 条规则、指南和最佳实践”:如果您可以将其作为非成员函数执行,则将其作为非成员函数执行(在同一个命名空间中)。
原因之一:隐式类型转换效果更好。一个例子:你有一个带有重载运算符*的复杂类。如果你想写 2.0 * aComplexNumber,你需要 operator* 是一个非成员函数。
另一个原因:更少的耦合。非成员函数的耦合度不如成员函数。这几乎总是一件好事。
每个运营商都有自己的考虑。例如,<< 运算符(用于流输出时,而不是位移)将 ostream 作为其第一个参数,因此它不能是您的类的成员。如果您正在实现加法运算符,您可能希望从双方的自动类型转换中受益,因此您也将与非成员一起使用,等等......
至于允许通过继承进行特化,一种常见的模式是根据虚拟成员函数来实现非成员运算符(例如,operator<< 在被传递的对象上调用虚函数 print())。
如果您计划实现流式运算符(<< 和 >>),那么它们将是非成员方法,因为您的对象位于运算符的左侧。
如果您计划实现 ->、() 或 [],它们自然是成员方法。
对于其他人(比较和数学),您应该查看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:
};
2operator+
将自动生成为非会员,这将使您受益于自动转换。并且它们将被有效地实现,operator+=
因此您只需编写一次代码。
如果你正在实现 op,那么很可能你需要实现 op=。即如果你重载了+操作符,那么你应该实现+=。如果您正在执行后增量或重载 + 运算符,请确保将 const 返回给对象。因此,如果您重载运算符 + ,则将其实现为非成员运算符并在其中使用 += 运算符。例如。
const A operator+(const A& lhs, const A& rhs)
{
A ret(lhs);
ret += rhs;
return ret;
}
对于二元运算符,成员函数的一个限制是左对象必须是您的类类型。这会限制对称地使用运算符。
考虑一个简单的字符串类:
class str
{
public:
str(const char *);
str(const str &other);
};
如果你实现operator+作为成员函数,whilestr("1") + "2"
会编译,"1" + str("2")
不会编译。
但是如果你将 operator+ 实现为非成员函数,那么这两个语句都是合法的。
没有什么比最佳实践更好的了,但这取决于您要重载的操作员..
例如。
>>和<<不能作为成员函数重载。
假设你想这样做:obj1 = 2 * obj2然后去非成员函数。
对于二元运算符重载,成员函数只需要 1 个参数(调用对象是隐式传递的),而非成员函数需要 2 个参数。