关于c++ class 接口设计的建议:你会如何命名这两个方法以使其显而易见?

Advice on c++ class interface design: how would you name these two methods to make them obvious?

我有一个非常简单的具体 class 表示 2D 中的一个点 space,它有两种方法可以在给定半径和角度的情况下移动点:一种修改对象本身, other 创建另一个对象,保持第一个不变:

template<class T =double> class cls_2DPoint
{
    ...
    cls_2DPoint<T>& polar_move(const T r, const double a) noexcept
       {
        x+=r*std::cos(a); y+=r*std::sin(a); return *this;
       }
    cls_2DPoint<T> polar_moved(const T r, const double a) const noexcept
       {
        return cls_2DPoint<T>(x+r*std::cos(a), y+r*std::sin(a));
       }
    ...
    T x,y;
};

这实际上是我正在使用的代码!在审查它时,我意识到这是一个鲁莽的设计:不明显,容易出错,使用户代码的可读性降低。 由于我正在努力寻找一个令人信服的替代方案,所以我想在这里征求意见:是否有通用的 conventions/guidelines 用于命名修改和非修改方法?是否有可以帮助我改进设计的最佳实践?

我的建议。

使用 namespace 代替 class 名称的前缀

namespace cls2D
{
   class Point { ... };
}

添加classVector

namespace cls2D
{
   class Point { ... };
   class Vector { ... };
}

定义运算符方法

定义适用于两种对象类型的运算符方法。如果可以的话,最好使用非成员函数。

namespace cls2D
{
   class Vector;

   class Point
   { 
      public:

         Point& operator+=(Vector v);
         Point& operator-=(Vector v);

      private:
         double x = 0;
         double y = 0;
      
   };

   class Vector
   {
      public:

         Vector& operator+=(Vector v);
         Vector& operator-=(Vector v);

      private:
         double x = 0;
         double y = 0;
   };

   Point from_polar(double r, double th);
   Point from_vector(Vector v);
   Vector from_point(Point p);

   Point operator+(Point p, Vector v);
   Point operator+(Vector v, Point p);
   Vector operator+(Vector v1, Vector v2);

   Vector operator-(Point p1, Point p2);
   Vector operator-(Vector v1, Vector v2);

}

请注意PointVector有相同的成员数据。因此,很容易只使用一个 class 来表示两者。但是,我认为它们是两个不同的抽象,应该是不同的 classes.

我删除了回答中的 template 部分,以便更简单地说明这个想法。

我假设您知道如何将必要的构造函数添加到 classes。

我会这样命名它们:

template<class T =double> class cls_2DPoint
{
    ...

    cls_2DPoint<T>& polarMovePoint(const T r, const double a) noexcept
       {
        x+=r*std::cos(a); y+=r*std::sin(a); return *this;
       }

    cls_2DPoint<T> polarMovePointClone(const T r, const double a) const noexcept
       {
        return cls_2DPoint<T>(x+r*std::cos(a), y+r*std::sin(a));
       }
    ...
    T x,y;
};

这种类型的标签会让我知道哪个函数移动了点本身,哪个函数创建了点的克隆然后移动了那个点。