【问题标题】:How to overload operator ==?如何重载运算符==?
【发布时间】:2014-03-27 07:25:58
【问题描述】:

我有A级 如何重载 operator == 来执行

A a,b,c;
if (a==b==c) {}

谁能帮帮我?

【问题讨论】:

  • 你最好使用(a == b && a == c)。如果你真的想要那种语法,你将需要一些非常丑陋的技巧。
  • 您只是想要一个operator== 还是可以实现a==b==c 的东西?
  • 你需要 2 个 operator==,一个接受 2 个 A 并返回一个 B,该 B 记住它的一个参数和第一次比较的结果,另一个接受一个 B 和一个 A 并返回一个B. B 可以根据上下文转换为 bool。

标签: c++ overloading operator-keyword


【解决方案1】:

非常简短的回答:不!
稍长一点的答案:不要尝试这个。

说明:每个 C++ 程序员都习惯于让比较运算符返回一个 bool 或可转换为 bool 的东西。只是因为输入 if (a==b) 之类的内容很自然。
因此,如果表达式a==b 返回一个布尔值x,那么a==b==c 将意味着将xc 进行比较。这根本没有意义。即使你让它编译,例如以这种方式比较整数,它不会产生您期望的结果。

所以,虽然技术上我可以想出一个解决方案来解决你似乎想要的(比较三个是否相等),但正确的做法是在 C++ 中始终如何完成:逻辑链二进制比较:

if (a==b && b==c) {}

对于那些想知道“技术可行但太难看”解决方案的人:
不要在现实世界中这样做!如果你这样做,你应该被解雇。)

template <class T>
struct multiCompareProxy {
  bool b;
  T const& t;

  explicit operator bool() const {return b;}
  multiCompareProxy operator==(T const& rhs) {
    return {b && t.equals(rhs), t};
  }
};

template <class T>
multiCompareProxy<T> operator==(T const& lhs, T const& rhs) {
  return {lhs.equals(rhs), lhs};
}

一个类现在只需要重载euqals 方法就可以了:Example

【讨论】:

  • template &lt;class T&gt; multiCompareProxy&lt;T&gt; operator==(T const&amp; lhs, T const&amp; rhs) / “只需要重载等号...”如果您选择了一个比 equals 更晦涩的名称并且有一个 enable_if 这将是一个合理的方法,但作为它是否会干扰(编译器错误)许多对这种比较逻辑不感兴趣的类的其他比较,也不是任何equals 函数。
  • 由于这是一个模板,因此只有在比较其类没有自己重载的op==的对象时,编译器才会考虑它。尽管如此,我同意它可以稍微改进一下,以免干扰其他不适合这种比较的类。但由于它只是一个永远不应该被释放的玩具实现,我认为生成一个工作沙盒示例就足够了。
  • "...类没有自己的重载 op==",除非该类的 == 本身就是一个模板。无论如何-同意暗示值得探索的东西很好。干杯。
【解决方案2】:

如果你出于某种原因真的想要这样做,你需要一个像这样的代理对象:

struct A {};
struct Proxy {};

Proxy operator==(const A& a, const A& b) {
    return {};
}

bool operator==(const Proxy& p, const A& b) {
    return true;
}

bool operator==(const A& a, const Proxy& p) {
    return true;
}


#include <iostream>

int main() {
    A a, b, c;
    if(a == b == c) {
        std::cout << "Bad.\n";
    }
}

但是不要这样做。像其他人一样使用(a == b) &amp;&amp; (a == c)

【讨论】:

  • 这显然会为每个三元比较返回 true,无论内容如何;-)
  • @ArneMertz 我正在展示!我不知道 OP 想要什么逻辑。
【解决方案3】:

这是可以做到的,它非常偶尔作为一种领域特定语言 (DSL) 有用,用于匹配非 C++ 程序员所期望的符号,但应谨慎避免其他用途,因为如果随意使用它会混淆(并惹恼)编写代码的程序员。

class A
{
    // ...

    bool equals(const A& rhs) const { return ... }

    struct X
    {
        X(const A& a, bool b) : a_(a), b_(b) { }
        X& operator==(const A& rhs) const { b_ &= a_.equals(rhs); return *this; }

        explicit operator bool() const { return b_; }
        // remove explicit pre C++11 / consider making it operator void*() ...

        const A& a_;
        mutable bool b_;
    };

    X A::operator==(const A& rhs) const
    {
        return X(*this, equals(rhs));
    }
};

(如果你有隐式构造函数,你可能更喜欢独立函数)。

同样的使用代理的hackery允许各种意想不到的符号,如3 &lt; x &lt; 9x == a1 || a2 || a3...再次,避免它们,除非它会对代码的维护者产生巨大的影响。可以使用(理想情况下,该代码与系统中的其他 C++ 代码有非常清晰的界限)。

作为此类技术的良好使用示例,请考虑 boost spirit 库,它不寻常地使用许多运算符来提供近似 BNF 符号的东西....

【讨论】:

  • a_ 上缺少const,没有理由使b_ 可变。 +explicit 在 C++11 中。
  • @MarcGlisse:请致电constexplicitb_ 是可变的,因为 X 是临时的,所以 operator== 应该是 const。我本可以返回另一个临时的X,但认为这无缘无故地挑战了优化器....
【解决方案4】:

您不能(减去丑陋的黑客攻击的可能性)重载 operator==(...) 以按照您指定的方式工作。

如果您考虑它会做什么,a == b 会变成 true 或 false(布尔值),那么您将留下 (&lt;bool&gt; == c)。做你想做的事情的正确方法是某种形式的(a==b) &amp;&amp; (b==c)

有时您可以重载运算符以按照您的描述工作,但它必须返回与它所采用的相同的类型。一个例子是:

class A
{
  A& operator+=(A const& rhs)
  {
     // operator logic
     return *this;
  }
}

这种情况有效,因为使用a += b += c,您将执行(b += c),这将返回一个A&amp;,其余的a.operator+=(...) 接受它作为参数。

【讨论】:

  • 好吧,我相信你可以,用一些可怕的代理类。但我绝对不会
  • 确实如此。很多事情都是可能的,但这并不意味着它们应该去做。
【解决方案5】:
bool operator==(T const & a, T const & b) {
     return /*boolean expr*/
}

如果你有课,你可以这样做:

class MyClass {
public:
    bool operator==(T const & rhs) const {
       return /*boolean expr*/
    }
}

并且不要连续使用 == 两次,你不能这样做:

a == b && b == c

【讨论】:

  • 他要求你的解决方案没有提供的行为 a == b == c。
  • 抱歉,我正在编辑所有问题。除此之外,这并没有使我的回复毫无用处。他想重载(但他不知道语法正确)。
  • 他明确表示他想重载它以执行给定的语法。
  • 好的,好吧。重读我认为你是对的。我只是希望重载 operator== 是一个有用的提示,可以在语义上执行他想要的。我投票给你。
【解决方案6】:

我会写:

bool operator==(const A& lhs, const A& rhs){ /* do actual comparison */ }

并使用and操作两次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-29
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多