C++向量运算符重载

C++ Vector Operator Overloading

本文关键字:重载 运算符 向量 C++      更新时间:2023-10-16

我正在尝试找到一个简单的示例程序,该程序重载数学向量的以下运算符。

Constructor  // create
= (equals)     // assign
+; -; +=; -=   // add sub
*; /; *=; /=   // multi divide
++; -- // plus minus
==    // compare
>; >=
<; <=
[]    // access a value

似乎找不到任何好的简单教程。我强调简单,因为我现在才学习这些东西。如果有人可以链接我甚至更好的程序,仅对其中一个运算符进行简单的重载作为示例,那将是令人难以置信的!

编写运算符时需要了解一些事项,这些运算符不经常与其他函数一起使用。

例如,赋值运算符将return *this,因为您更改了向量的值:

class v {
public:
  double x_, y_;
  v& operator += (const v& rhs)
  {
     _x += rhs._x;
     _y += rhs._y;
     return *this;
  }
};

另一个有趣的,前++和后++不同,只是因为一个未使用的参数:

class v {
public:
  double x_, y_;
  v& operator ++ (); // ++v
  v& operator ++ (int); // v++
};

"等于"(赋值)是另一个在使用指针时很棘手的问题。对于向量,它通常不会成为问题,但是如果您定义一个向量 V 并将其分配给自身,则必须小心:

class v {
public:
  double x_, y_;
  v& operator = (const v& rhs)
  {
    if(this != &rhs)
    {
      x_ = rhs.x_;
      y_ = rhs.y_;
    }
    return *this;
  }
};

在您的情况下,if()肯定没有用,但请考虑执行以下操作:

   delete p_;
   p_ = new foo;
   p_->x_ = rhs.p_->x_;

如果&rhs == this,则delete p_删除了rhs指针!这意味着在第 3 行访问它是一个错误。

其余的应该很容易使用。比较运算符返回boolconst

class v {
public:
  double x_, y_;
  bool operator == (const v& rhs) const
  {
    return x_ == rhs.x_ && y_ == rhs.y_;
  }
};

虽然,从 C++20 开始,您应该只声明三向比较运算符<=>,这允许编译器为您实现所有其他比较运算符。这个返回一个负数(较小:a <b)、0(等于:a> b)。

不确定是什么使向量变大或变小,在这个例子中我使用了 (0, 0) 的长度:

class v {
public:
  double x_, y_;
  int operator <=> (const v& rhs) const
  {
    if(x_ == rhs.x_ && y_ == rhs.y_)
    {
      return 0;
    }
    return length() > rhs.length() ? 1 : -1;
  }
};

[]运算符除外。该版本有两个版本:

class v {
public:
  // I would imagine you'd use an array but as a simple example...
  double x_, y_;
  double operator [] (int idx) const
  {
    return idx == 0 ? x_ : y_;
  }
  v_ref operator [] (int idx)
  {
    v_ref v(this, idx);
    return v;
  }
};

如您所见,[] 运算符的非常量版本返回一个引用。这是必要的,所以你可以写一些东西,这样:

r[3] = 7.3;

r[3]返回该引用,则以 7.3 作为参数调用引用的赋值。(请注意,如果您只有 2 个值时使用 3 作为索引,我们可能会抛出错误:0 和 1 - 此处未显示)

class v_ref
{
public:
  v *p_;
  int i_;
  v_ref(v *p, int i)
    : p_(p), i_(i)
  {
  }
  operator = (double q)
  {
     // again, I suppose you'd use an array instead!
     if(i_ == 0)
     {
       p_->x_ = q;
     }
     else
     {
       p_->y_ = q;
     }
  }
};

假设你想要一些安全性,矢量指针可以使用引用计数器,这样你就知道一个主矢量对象是否在其所有引用对象之前被删除......

另一个注意事项:我想你的构造函数会分配一个双精度数组(或使用std::vector<double>类型......如果使用 new,请记住在析构函数中删除,这时赋值运算符中的if()非常重要。