Should I add override to the overridden methods in Circle, like this?
IMHO, the term adds value.
Suppose I write the following (in the main):
Point o(0, 0);
Point a(0, 1);
Point b(1, 0);
Shape* shapes[] = { new Circle(a, b),
new Circle(o, a, b),
new Circle(o, 1) };
With these lines, my compiler now reports 2 additional errors (with 2 notes) ...
error: no matching function for call to ‘Circle::Circle(Point&, Point&)’
note: no known conversion for argument 2 from ‘Point’ to ‘int’
also
error: no matching function for call to ‘Circle::Circle(Point&,Point&,Point&)’
note: candidate expects 2 arguments, 3 provided
Does the last line influence the need to use (or not use) c'tor and d'tor?
I think not.
Even before this 'code addition' the compiler gives warnings about having virtual functions and accessible non-virtual d'tors. These warnings might be fixed by declaring the (missing) dtors virtual, but ... well, here they simply point out that your code does not compile clean.
You should complete your [MCVE]. As is, you provide insufficient information for a 'careful pick' of what (ctors, dtors) you do or do not provide.
I usually come at these issues in another way. My personal coding 'standard' includes the following 6 ideas that, when I am in doubt, or don't understand why, I simply add these lines to my classes, in a private section.
// coding standard: disallow when not used
T(void) = delete; // default ctor (1)
~T(void) = delete; // default dtor (2)
T(const T&) = delete; // copy ctor (3)
T(const T&&) = delete; // move ctor (4)
T& operator= (const T&) = delete; // copy assignment (5)
T& operator= (const T&&) = delete; // move assignment (6)
By 'T', I mean for you to replace the 'T' with your class name. It is easy, so I usually add to each of my classes. i.e. repeat the above 6 lines, in a private area of each class, with T replaced.
Now, your compiler can complain about something specific. I have found it quick to learn how to fix the issues this shows, so I offer one example.
If you ever get a MCVE, try the following additions:
class Shape //abstract class//
{
public:
virtual double getArea() const=0;
virtual double getPerim() const=0;
private:
// coding standard - disallow when not used
Shape(void) = delete; // default ctor (1)
~Shape(void) = delete; // default dtor (2)
Shape(const Shape&) = delete; // copy ctor (3)
Shape(const Shape&&) = delete; // move ctor (4)
Shape& operator= (const Shape&) = delete; // copy assignment (5)
Shape& operator= (const Shape&&) = delete; // move assignment (6)
};
Since the Shape class has only the compiler injected default ctor, (and dtor) I think these deletes will trigger an error in the compiler.
The idea is simply that if 'other code' (such as standard containers, or algorithms, or the compiler) does things with Shape and uses one or adds one or more of these 6, the compiler will notice that they are deleted, and generate an error for you.
I have been surprised by the standard containers as they often use more of these 6 than I expect. With the ctor deleted, I get a chance to decide if I want to write something specific to this effort, or if the compiler-provided-default might be ok ... it often is. In which case I simply comment out one or more of the 6 delete lines, then compile again.
I resist commenting out these deletes. Sometimes it happens that one of my errors will trigger a use for one of the 6. Got to be watching for those, too.
These 6 lines (and there are other's you might choose to consider) will keep you informed of what methods the compiler is providing as a 'service'. (Most of the time, I dislike implicit conversions, too.)
So, instead of trying to understand why you might want or not want one these 6, this technique allows you find out what your program requires. Using each line (i.e. disabling at least long enough to see where and what for), the compiler complaints show where that 'move ctor' or 'move assignment' is being used. Very helpful when you know you didn't do it!