3

我试图找到一个简单的示例程序,它重载了数学向量的以下运算符。

Constructor  // create

= (equals)     // assign

+; -; +=; -=   // add sub

*; /; *=; /=   // multi divide

++; -- // plus minus

==    // compare
>; >=
<; <=

[]    // access a value

似乎找不到任何好的简单教程。我强调简单,因为我现在才学习这些东西。如果有人可以链接我,或者甚至更好地为一个操作员编写一个简单的重载作为示例,那将是不可思议的!

4

1 回答 1

10

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

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

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

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

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 行访问它是一个错误。

其余的应该很容易使用。比较运算符返回bool并且是const

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)或正数(较大: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作为参数调用。(请注意,如果您使用 3 作为索引,而您只有 2 个值: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;
     }
  }
};

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

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

于 2013-10-31T02:55:29.757 回答