Hi all,
This is our base class called,
Shape:
1 2 3 4 5 6 7 8 9
|
class Shape {
public:
virtual Point center() const = 0; // pure virtual
virtual void move(Point to) = 0;
virtual void draw() const = 0; // draw on current "Canvas"
virtual void rotate(int angle) = 0;
virtual ~Shape() {} // destructor
// ...
};
| |
And this
Circle type is our first derived class: (A
Triangle shape can also this way derive from our bass class)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
class Circle : public Shape {
public:
Circle(Point p, int rad); // constructor
Point center() const override { return x; }
void move(Point to) override { x = to; }
void draw() const override;
void rotate(int) override {} // nice simple algorithm
private:
Point x; // center
int r; // radius
};
| |
This is our
Smiley subclass:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class Smiley : public Circle { // use the circle as the base for a face
public:
Smiley(Point p, int rad) : Circle{p,r}, mouth{nullptr} { }
~Smiley()
{
delete mouth;
for (auto p : eyes)
delete p;
}
void move(Point to) override;
void draw() const override;
void rotate(int) override;
void add_eye(Shape* s){ eyes.push_back(s); }
void set_mouth(Shape* s);
virtual void wink(int i); // wink eye number i
// ...
private:
vector<Shape*> eyes; // usually two eyes
Shape* mouth;
};
| |
We use the function
read_shape() to read a
Shape from the user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
enum class Kind { circle, triangle, smiley };
Shape* read_shape(istream& is) // read shape descriptions from input stream is
{
// ... read shape header from is and find its Kind k ...
switch (k) {
case Kind::circle:
// read circle data {Point,int} into p and r
return new Circle{p,r};
case Kind::triangle:
// read triangle data {Point,Point,Point} into p1, p2, and p3
return new Triangle{p1,p2,p3};
case Kind::smiley:
// read smiley data {Point,int,Shape,Shape,Shape} into p, r, e1, e2, and m
Smiley* ps = new Smiley{p,r};
ps−>add_eye(e1);
ps−>add_eye(e2);
ps−>set_mouth(m);
return ps;
}
}
| |
How can the above function is implemented? Something like this?
E.g., when the user inputs 3 Points (pairs of int-s), and then ctrl+z, we infer from the input that k =
Triangle
When a Point and an int, => k =
Circle
And when a Point, an int and three other shapes, like above, so k =
Smiley
Right up to here?
Now this
dynamic_cast<> is used:
1 2 3 4 5 6 7
|
Shape* ps {read_shape(cin)};
if (Smiley* p = dynamic_cast<Smiley*>(ps)) { // ... does ps point to a Smiley?
// ... a Smiley; use it
}
else {
// ... not a Smiley, try something else ...
}
| |
Here the if-condition checks whether the shape returned by
read_shape() matches the characteristics of a
Smiley shape or not. If so, then we use it.
The question here is that, what is the difference between code written above and one without a
dynamic_cast<>?
1 2 3 4 5 6 7
|
Shape* ps {read_shape(cin)};
if (Smiley* p = ps) { // ... does ps point to a Smiley?
// ... a Smiley; use it
}
else {
// ... not a Smiley, try something else ...
}
| |
What is the benefit of that
dynamic_cast<> here?
PS: Please use simple language; I'm not a C++ expert! :)