问题描述
我有一个非常简单的具体类,它表示 2D 空间中的一个点,它有两种方法来移动给定半径和角度的点:一种修改对象本身,另一种创建另一个对象,保持第一个不变:
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;
};
这实际上是我正在使用的代码!在审查它时,我意识到这是一个鲁莽的设计:不明显,容易出错,使用户代码的可读性降低。 由于我正在努力寻找令人信服的替代方案,因此我想在这里寻求建议:是否有命名修改和非修改方法的一般约定/指南?是否有最佳实践可以帮助我改进设计?
解决方法
我的建议。
类名使用namespace
代替前缀
namespace cls2D
{
class Point { ... };
}
添加类Vector
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);
}
请注意,Point
和 Vector
具有相同的成员数据。因此,很容易只使用一个类来表示两者。但是,我认为它们是两种不同的抽象,应该是不同的类。
我删除了答案中的 template
部分,以便更简单地说明这个想法。
我假设您知道如何将必要的辅助函数添加到类中。
,我会这样命名它们:
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;
};
这种类型的标签会让我知道哪个函数移动了点本身,哪个函数创建了点的克隆,然后移动了它。