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