为什么我应该将C ++运算符作为全局函数(STL)重载?有什么警告?

时间:2011-09-28 05:23:01

标签: c++ operator-overloading globals

为什么我要将C ++ operator()重载为全局而非成员函数。例如,==运算符。

为什么这样做?例如在STL库中。

3 个答案:

答案 0 :(得分:12)

通常的规则是修改左手对象的操作员 成员和返回新对象的二元运算符是免费的 功能;后者的主要动机是因为编译器 不会转换左侧以匹配成员;如果你的班级 支持任何隐式转换,然后支持所有常用的二进制转换 运营商应该是自由职能,因此适用相同的转换规则 对于左手侧和右手侧,例如:

class Complex
{
public:
    Complex(double r, double i = 0.0);
    bool operator==( Complex const& other ) const;
};

Complex a;
//  ...
if ( a == 1.0 ) // OK
//  ...
if ( 1.0 == a ) // error.

但:

class Complex
{
public:
    Complex(double r, double i = 0.0);
    friend bool operator==( Complex const& lhs, Complex const& rhs ) const;
};

Complex a;
//  ...
if ( a == 1.0 ) // OK
//  ...
if ( 1.0 == a ) // OK

实现这一目标的一个优雅方法是定义基本操作 成员函数的术语 - 对于像+-这样的东西,这些会 是operator+=operator-=;为了比较,你需要定义 任意约定,成员isEqualcompare(会 根据结果​​返回<==>零,然后继承 一个模板:

template <typename T>
class ArithmeticOperators
{
    friend T operator+( T const& lhs, T const& rhs )
    {
        T result( lhs );
        result += rhs;
        return result;
    }
    //  And so on, for all of the binary operators.
};

class Complex : public ArithmeticOperators<Complex>
{
public:
    //  ...
    Complex& operator+=( Complex const& other );
    //  etc.
};

请注意,operator <op>=有一些争论 函数自由函数:自由函数的事实 将非const引用作为其第一个参数,因此需要一个 左值(与内置operator <op>=一样)。这似乎不是 然而,通常的做法可能是因为operator=必须是一个 成员,处理operator <op>=似乎更自然 同样的人。

答案 1 :(得分:2)

如果我没记错的话,operator =必须是会员功能。关于operator ==,我认为你实际上并不是指全局而是自由函数(STL并不是全局定义运算符)。有几件事需要考虑,一个是与类本身脱钩:如果您的运算符可以根据类的公共接口进行定义,那么最好以这种方式实现它以保持对实现内部的访问到最低限度。另一个基本优点是可以实现一个操作符,其中你的类型作为第二个操作数,考虑类型T和U之间的相等:

bool operator ==( T const& t, U const& u ){ ... }
bool operator ==( U const& t, T const& u ){ ... }

如果可以同等地比较T和U类型的对象,那么t == uu == t都有效并且两者都产生相同的结果。如果你将这个运算符定义为一个成员函数,那么一个将在T的实现中,另一个在U的实现中。现在考虑U是你控制之外的第三方类型,或者更好的是一个基本类型,如int,现在没有其他方法可以提供此类运算符,但提供它的免费功能版本。

答案 2 :(得分:0)

将成员函数与参数匹配的规则与匹配自由函数的第一个参数的规则不同。我不确定它们究竟是如何不同的,但由于它们不同,实际上最好将大多数二元运算符实现为自由函数而不是成员函数,以便参数匹配对两个参数对称运行。

除了postfix ++之外,这是因为它不是真正的二元运算符,只有在重载它时才会播放一个,以便有一种方法可以区分它和前缀{{1 }}