Search code examples
c++classmethodsnaming-conventionsconventions

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


I have a very simple concrete class that represents a point in 2D space, it has two methods to shift the point given a radius and an angle: one modifies the object itself, the other creates another object leaving the first one unchanged:

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;
};

This is actually code that I'm using! While reviewing it I realized that this was a reckless design: not obvious, error prone, making the user code less readable. Since I'm struggling to find a convincing alternative, I thought to ask advice here: are there general conventions/guidelines for naming modifying and non-modifying methods? Are there best practices that could help me here to improve the design?


Solution

  • My suggestions.

    Use namespace instead of prefix for class name

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

    Add class Vector

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

    Define operator methods

    Define operator methods that work with the two object types. Prefer non-member functions if you can get away with it.

    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);
    
    }
    

    Please note that Point and Vector have the same member data. Hence, it's tempting to use just one class to represent both. However, I think of them as two different abstractions and deserve to be different classes.

    I removed the template part in my answer to make illustration of the idea simpler.

    I assume you know how to add the necessary costructors to the classes.