简体   繁体   English

“最佳”或“正确”的地方平等运算符在哪里?

[英]Where is the "best" or "correct" place place equality operators?

I know there are many places to implement your equality operators in c++.我知道在 c++ 中有很多地方可以实现您的相等运算符。 However, I wonder if there is some wisdom as to where best to place them?但是,我想知道将它们放在哪里最好? I can foresee 3 possible different cases where different rules might apply.我可以预见 3 种可能适用不同规则的不同情况。 In each of the three cases are any of the options considered better or worse?在这三种情况下,任何一种选择被认为是更好还是更差?

Case 1, equality with primitives and standard types and itself:情况 1,与原语和标准类型及其本身相等:

//option 1, outside the class with friend 
class foo1;

friend bool operator==(const foo1& lhs, const int& rhs);
friend bool operator==(const int& lhs, const foo1& rhs);
friend bool operator==(const foo1& lhs, const foo1& rhs);

//option 2, inside class with out friend for primitives
class foo1
{
    bool operator==(const int& other) const;
    bool operator==(const foo1& other) const;
};

Case 2, two custom classes:案例2,两个自定义类:

//option 1, outside the class using friend
class foo2;
class bar2;

friend bool operator==(const foo2& lhs, const bar2& rhs);
friend bool operator==(const bar2& lhs, const foo2& rhs);

//option 2, inside the class using friend
class foo2; //forwards declaration
class bar2; //forwards declaration

class foo2
{
    friend bool operator==(const foo2& lhs, const bar2& rhs) const;
    friend bool operator==(const bar2& lhs, const foo2& rhs) const;
};
class bar2
{
    friend bool operator==(const foo2& lhs, const bar2& rhs) const;
    friend bool operator==(const bar2& lhs, const foo2& rhs) const;
};

Case 3, sub-classes:案例3,子类:

//option 1, outside all classes using friend
class foo3
{
    class bar3;
}

friend bool operator==(const foo3::bar3& lhs, const foo3::bar3& rhs);

//option 2, inside the scope of the owning class using friend
class foo3
{
    class bar3;

    friend bool operator==(const foo3::bar3& lhs, const foo3::bar3& rhs);
}

//option 3, inside the class with out friend
class foo3
{
    class bar3
    {
        bool operator==(const foo3::bar3& other) const;
    };
}

Derived classes have already been answered here: What's the right way to overload operator== for a class hierarchy?派生类已经在这里得到解答: What's the right way to overload operator== for a class hierarchy?

Operators in namespaces have already been answered here: Namespaces and Operator Overloading in C++命名空间中的运算符已在此处得到解答: C++ 中的命名空间和运算符重载

Edit: fixed compiler errors, spelling errors, and constified member functions编辑:修复编译器错误、拼写错误和 constified 成员函数

I think this topic is certainly well described in more then one place.我认为这个话题肯定在不止一个地方得到了很好的描述。 At the moment, unfortunately, I "just" have with me internet and C++ Templates .目前,不幸的是,我“只是”拥有互联网和C++ 模板 (In that book, section 21.2.2 addresses the related topic of how you can define == for a class such that != is automatically defined too.) (在那本书中,第 21.2.2 节讨论了如何为 class 定义==的相关主题,这样!=也会自动定义。)

As regards your question, at the beginning of section 21.2.1 from the linked book, a slight preference for non-member comparison operators is expressed关于您的问题,在链接书中第 21.2.1 节的开头,表达了对非成员比较运算符的轻微偏好

Because operator== is meant to be symmetrical with respect to its arguments, it is preferable to declare it as a namespace scope function.因为operator==意味着相对于它的 arguments 是对称的,所以最好将其声明为命名空间 scope function。

(In that very section, there's also a reference, at page 499, to what I refer to in the following as "hidden friends".) (在那个部分,第 499 页也有一个参考,我在下文中将其称为“隐藏的朋友”。)

On the other hand, I would also quote this answer , where Barry claims (and supports it with example snippets) that另一方面,我也会引用这个答案巴里声称(并通过示例片段支持它)

There is no rule to prefer a member to a non-member function (or vice versa).没有规则偏爱成员而不是非成员 function(反之亦然)。

Honestly, given the stature of people advocating one or the other solution, I feel I simply don't have the tools yet (knowledge and experience) to express a preference.老实说,鉴于提倡一种或另一种解决方案的人的地位,我觉得我根本没有工具(知识和经验)来表达偏好。

As regards making them friend functions, I'd just like to point out that one option is to declare them only inside the class .至于使它们成为friend功能,我只想指出一种选择是仅在 class 内声明它们 This makes them "hidden friends", as described in The Power of Hidden Friends in C++ , which has the advantages therein explained.这使他们成为“隐藏的朋友”,如C++ 中的 The Power of Hidden Friends 中所述,其中解释了其优点。 Those advantages apply to functions in general, and not just comparison operators.这些优点通常适用于函数,而不仅仅是比较运算符。 (This "technique" makes use of ADL .) (这种“技术”利用了ADL 。)

Here's one consequence of defining operator== as "hidden friend" of Foo .这是将operator==定义为Foo的“隐藏朋友”的一个结果。 This is Foo ,这是Foo ,

struct Foo {
    friend bool operator==(Foo const&, Foo const&) {
        return true;
    }
};

where operator== is an "hidden friend", and this is Bar ,其中operator==是“隐藏的朋友”,这是Bar

struct Bar {
    operator Foo() { return Foo{}; };
};

which is convertible to Foo .可转换为Foo

Expectedly, code like Foo{} == Foo{} works, because an operator== is defined for the pair of arguments Foo - Foo .预计,像Foo{} == Foo{}这样的代码可以工作,因为operator==是为 arguments Foo - Foo对定义的。

Maybe less expectedly, code like Bar{} == Bar{} does not work instead, which protects you from accidental implicit conversions.也许不太出乎意料,像Bar{} == Bar{}这样的代码不起作用,它可以保护您免受意外的隐式转换。

Had you also delcared bool operator==(Foo const&, Foo const&);如果您还定义了bool operator==(Foo const&, Foo const&); outside the class, then the definition of that operator== , which is still inside the class, would become visible to the outside, and Bar{} == Bar{} would be fine.在 class 之外,则仍位于 class 内部的operator==定义将对外部可见,并且Bar{} == Bar{}就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM