【问题标题】:How to implement both scalar and vector addition using the += operator?如何使用 += 运算符实现标量和向量加法?
【发布时间】:2013-03-15 18:20:14
【问题描述】:

我正在研究一个 Vector2D 类,我认为使用 +=/+ 运算符实现向量加法和标量加法都很有意义。

麻烦的是,我真的不知道如何解决这个明显的论点模棱两可,这是 Clang 所说的:

vector2d_test.cpp:17:16: error: use of overloaded operator
      '+=' is ambiguous (with operand types 'Vector2D<float>' and 'int')
        vector += 1;
        ~~~~~~ ^  ~~~~~~~
vector2d.hpp:34:18: note: candidate function
    Vector2D<T>& operator+=(const Vector2D<T>& other)
                 ^
vector2d.hpp:41:18: note: candidate function
    Vector2D<T>& operator+=(const T summand) const

这是两个函数:

Vector2D<T>& operator+=(const Vector2D<T>& other)
{
    x += other.x;
    y += other.y;
    return *this;
}

template <typename S>
Vector2D<T>& operator+=(const S summand) const
{
    x += summand;
    y += summand;
    return *this;
}

所以...知道我能做些什么吗?

【问题讨论】:

    标签: c++ operator-overloading vector-graphics


    【解决方案1】:

    你都写了你的错误信息。您试图添加到 int 类型的向量变量,但您的向量有浮点数。应该是:

    vector += 1f;
    

    vector += 1.0;
    

    看看。当你有这个向量时:

    Vector2D<float> vector;
    

    这个向量对应的函数有头:

    Vector2D<T>& operator+=(const float summand) const;
    

    现在第二个无关紧要。当您尝试添加到向量 1 时,您正在尝试调用函数:

    Vector2D<T>& operator+=(const int summand) const;
    

    你没有声明。这就是编译器向您发送错误消息的原因——它找不到合适的函数。

    【讨论】:

      【解决方案2】:

      不清楚您要做什么。 operator+= 除非他们是成员,否则您发布的功能是不合法的。而如果 他们是成员,你有类似的东西:

      Vector2D<float> v;
      //   ...
      v += 1;
      

      Vector2D&lt;float&gt;::operator+=( Vector2D&lt;float&gt; const&amp; ) 函数是不可调用的,因此不会有歧义。如果 函数不是成员,那么它们应该写成:

      template <typename T>
      Vector2D<T>& operator+=( Vector2D<T>& lhs, Vector2D<T> const& rhs );
      template <typename T, typename U>
      Vector2D<T>& operator+=( Vector2D<T>& lhs, U rhs );
      

      即使在这种情况下,第一个也不能用rhs 调用 输入int,所以没有歧义。

      编辑:

      我错过了您发布的第二个结尾处的const。 这是你的一个明显的错字,它仍然没有改变 任何东西,除非你也有一些隐式转换 Vector2D(这可能不是一个好主意);否则, 第一个版本仍然不可调用。如果有,例如, 从intVector2D 的隐式转换,然后您调用 += 在非常量 Vector2D 上,那么第一个重载是 隐式第一个参数的更好匹配(这导致 this 指针),因为它是完全匹配的,甚至没有 cv 转换,但第二个函数更适合 第二个参数,因为模板实例化的结果 在完全匹配中。所以这个调用是模棱两可的。

      【讨论】:

      • 歧义必须来自Vector2D&lt;T&gt; 的构造函数采用int。一个人还观察到第二个成员的错误const,导致我们得出结论,这绝对是不够的代码。
      • @DeadMG 虚假的const 显然是错误的,以至于我忽略了它。 operator+= 应该永远const。但是,正如我在编辑中指出的那样,您仍然需要隐式转换才能使调用变得模棱两可。
      • 哎呀,那个 const 实际上是问题所在:P
      • @futlib 即使使用const,重载决议也应该可以工作,除非你有不需要的隐式转换。考虑让你的构造函数explicit
      【解决方案3】:

      最简单的方法是在 Vector2D ala 中定义函数:

      Vector2D& operator+=(const Vector2D& rhs)
          { ...each this element += rhs's corresponding element... }
      
      Vector2D& operator+=(const T& summand)
          { ...each this elements += summand... }
      
      friend Vector2D operator+(Vector2D lhs, const Vector2D& rhs) { return lhs += rhs; }
      
      friend Vector2D operator+(Vector2D lhs, const T& rhs) { return lhs += rhs; }
      

      注意事项:

      • 非成员函数是friends,这样可以方便地内联定义它们
      • 函数不应该是const(你的问题中有一个)
      • 将尝试通常的转换,所以如果Tfloat,那么ints 将工作得很好,除非你做一些有趣的事情,比如给Vector2D 一个来自单个int 的隐式构造函数,从而做出选择转换模棱两可

      【讨论】:

      • @juanchopanza 正如他所说,您在类中定义(或至少声明)它,因此它具有类类型的隐式第一个参数。
      • @JamesKanze 在编辑之前,它说“将函数定义为 Vector2D 中的朋友......”。
      • @juanchopanza: 是的 - 很抱歉造成混乱......第一次忘记列出朋友......
      猜你喜欢
      • 2017-04-23
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      • 2018-10-16
      • 1970-01-01
      相关资源
      最近更新 更多