00 //===================================================================
01 // Name        : shapes.h
02 // Author      : Simonas Saltenis
03 // Version     :
04 // Description : Shapes hierarchy with a possibility to visit them
05 //===================================================================
06 
07 #ifndef SHAPES_INCLUDED
08 #define SHAPES_INCLUDED
09 
10 class Visitor;
11 
12 class Shape    // abstract shape
13 {
14 public:
15     virtual void accept(Visitor&) = 0;    // note: no const, both the shape and the visitor are allowed to be changed
16     virtual     ~Shape() {}
17 };
18 
19 struct Circle: public Shape
20 {
21     double r;
22 
23     Circle(double radius) : r{radius} {};
24     void accept(Visitor& v) override;
25 };
26 
27 struct Rectangle: public Shape
28 {
29     double l, w;
30 
31     Rectangle(double length, double width) : l{length}, w{width} {};
32     void accept(Visitor& v) override;
33 };
34 
35 // Other shape specializations...
36 
37 class Visitor  // abstract visitor: provides "visit" overloads for all the classes in the hierarchy
38 {
39 public:
40     virtual void visit (Circle&)    = 0;
41     virtual void visit (Rectangle&) = 0;
42     virtual     ~Visitor() {}
43 };
44 
45 // The "accept" methods of all the classes in the hierarchy just call the corresponding overload of "visit" from the visitor.
46 // Thus, the double-dispatch is achieved. When "accept" on a shape is called:
47 // first, the "accept" corresponding to the type of the shape is invoked (first dispatch),
48 // then, the "visit"(overload for that shape) corresponding to the type of the visitor is called (second-dispatch)
49 //
50 
51 inline void Circle::accept(Visitor& v)    { v.visit(*this); }
52 inline void Rectangle::accept(Visitor& v) { v.visit(*this); }
53 
54 #endif // SHAPES_INCLUDED
55