GetArea() returns a double, so the statement becomes in pseudo code return a value of type double |
Now, that is a great trick! I will remember it.
Yes, this is also found in my book's current chapter, saying:
C++ 11 introduces the override key word to help prevent subtle errors when overriding virtual functions, given the example:
Base Class:
virtual void functionA(int arg) const;
Derived Class:
virtual void functionA(long arg) const;
Which, if override were used, this subtle error would prevent the program from running. Or, as is the case with Visual Studio, throws an error saying
'Derived': cannot instantiate abstract class
Having it like this, there would be no need for the accessor in the base class. It also makes having the 'private member variable' in the base class obsolete. (At least in my humble opinion).
Imagine a system where the radius can be changed via Scale function. How often is it changed? How often is are these values queried? Should we calculate the Area every time asked? Or should we store the Area in a variable and just return it's value when asked? |
In such scenario the calculation should be carried out, and the result be stored in a variable and returned when asked. It
is an important point I haven't taken into consideration.
Let me qualify my last statement.
I have drawn the conclusion, that, iff a class should be pure abstract, and this pure abstract class has a virtual function that does the calculation and returns the result, there is no need for having a 'private member variable' to hold the result of said calculation. Neither would there be need or reason for having a mutator function that is a concrete method.
It is the problem itself, viewing it as 'isolated', there will be no changes made to this project once it is finished and the problem solved. This is the reason why a thought about 'What, if ...' never occured to me.
... the private access specifier that should really have been protected access specifier etc.
I disagree. It seems easy to make the data protected, one can access it easily from the derived classes. |
Wouldn't it be fair to say: 'Once you know and understand, it becomes easy.'? ;-)
As to your link, you would laugh if I told you that, shortly after reading and replying, I found this exact discussion over at stackexchange. I am also aware of the existence of isocpp, landed there while doing research about a particular subject. (And this is a wonderful resource, as it drives the point home by looking at it from various angles, and describes things in a way easy to understand.)
I also do my 'homework' if you will, researching topics, that - had I not set out on the journey to learn C++, probably would never have learned about. (Translating to: How often does a 'normal' person dig deeper into Spectral Analysis or learning about it?) Programming, and solving problems programmatically, it opens up whole new worlds of interesting (more or less) topics to learn about, while trying to solve a problem.)
-
One thing is still left unanswered: 'HOW can the problem be solved, given the problem statement, WITHOUT introducing any new functions to the base class, by HAVING a 'private member variable', AND a set of derived classes that do assign a value to it? (Yes, you may say there is no mention of not introducing any more functions than those named in the problem statement; Yet, if there should be, it is mentioned explicitly in a NOTE section beneath the problem statement.)
If you find it is not worth to try, it would be a waste of your precious time to go looking for an answer as there simply is none, simply say - forget it -.
-
This is what I have changed the code to (Notice that I haven't introduced all of your ideas, no namespace (I haven't learned it and want to understand before going about using it.), because the important thing is to get the basics right. I also kept the variables according to the problem statement. This also applies to the methods. And of course no catch and/or exception (topic of next chapter) :-)):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#ifndef BASIC_SHAPE_H_
#define BASIC_SHAPE_H_
class BasicShape
{
private:
double area;
protected:
void setArea(double);
public:
virtual ~BasicShape() = 0;
double getArea() const;
virtual double calcArea() = 0;
};
#endif
|
Implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include "BasicShape.h"
BasicShape::~BasicShape()
{
}
void BasicShape::setArea(double ar)
{
area = ar;
}
double BasicShape::getArea() const
{
return area;
}
|
Derived Class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
#ifndef CIRCLE_H_
#define CIRCLE_H_
#include "BasicShape.h"
class Circle : public BasicShape
{
private:
long centerX;
long centerY;
double radius;
public:
Circle::Circle(long x, long y, double r) : BasicShape()
{
centerX = x;
centerY = y;
radius = r;
BasicShape::setArea(calcArea());
}
~Circle()
{ }
long getCenterX() const;
long getCenterY() const;
double getRadius() const;
virtual double calcArea() override;
};
#endif
|
Implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#include "Circle.h"
double Circle::calcArea()
{
setArea(3.1415927 * radius * radius);
return getArea();
}
long Circle::getCenterX() const
{
return centerX;
}
long Circle::getCenterY() const
{
return centerY;
}
double Circle::getRadius() const
{
return radius;
}
|