# Design patterns Visitor Pattern Visitor Pattern example in C++

## Example

``````struct IShape
{
virtual ~IShape() = default;

virtual void print() const = 0;
virtual double area() const = 0;
virtual double perimeter() const = 0;
// .. and so on
};
``````

Visitors can be used:

``````// The concrete shapes
struct Square;
struct Circle;

// The visitor interface
struct IShapeVisitor
{
virtual ~IShapeVisitor() = default;
virtual void visit(const Square&) = 0;
virtual void visit(const Circle&) = 0;
};

// The shape interface
struct IShape
{
virtual ~IShape() = default;

virtual void accept(IShapeVisitor&) const = 0;
};
``````

Now the concrete shapes:

``````struct Point {
double x;
double y;
};

struct Circle : IShape
{

// Each shape has to implement this method the same way
void accept(IShapeVisitor& visitor) const override { visitor.visit(*this); }

Point center;
};

struct Square : IShape
{
Square(const Point& topLeft, double sideLength) :
topLeft(topLeft), sideLength(sideLength)
{}

// Each shape has to implement this method the same way
void accept(IShapeVisitor& visitor) const override { visitor.visit(*this); }

Point topLeft;
double sideLength;
};
``````

then the visitors:

``````struct ShapePrinter : IShapeVisitor
{
void visit(const Square&) override { std::cout << "Square"; }
void visit(const Circle&) override { std::cout << "Circle"; }
};

struct ShapeAreaComputer : IShapeVisitor
{
void visit(const Square& square) override
{
area = square.sideLength * square.sideLength;
}

void visit(const Circle& circle) override
{
}

double area = 0;
};

struct ShapePerimeterComputer : IShapeVisitor
{
void visit(const Square& square) override { perimeter = 4. * square.sideLength; }
void visit(const Circle& circle) override { perimeter = 2. * M_PI * circle.radius; }

double perimeter = 0.;
};
``````

And use it:

``````const Square square = {{-1., -1.}, 2.};
const Circle circle{{0., 0.}, 1.};
const IShape* shapes = {&square, &circle};

ShapePrinter shapePrinter;
ShapeAreaComputer shapeAreaComputer;
ShapePerimeterComputer shapePerimeterComputer;

for (const auto* shape : shapes) {
shape->accept(shapePrinter);
std::cout << " has an area of ";

// result will be stored in shapeAreaComputer.area
shape->accept(shapeAreaComputer);

// result will be stored in shapePerimeterComputer.perimeter
shape->accept(shapePerimeterComputer);

std::cout << shapeAreaComputer.area
<< ", and a perimeter of "
<< shapePerimeterComputer.perimeter
<< std::endl;
}
``````

Expected output:

``````Square has an area of 4, and a perimeter of 8
Circle has an area of 3.14159, and a perimeter of 6.28319
``````

Demo

Explanation:

• In `void Square::accept(IShapeVisitor& visitor) const override { visitor.visit(*this); }`, the static type of `this` is known, and so the chosen (at compile time) overload is `void IVisitor::visit(const Square&);`.

• For `square.accept(visitor);` call, the dynamic dispatch through `virtual` is used to know which `accept` to call.

Pros:

• You may add new functionality (`SerializeAsXml`, ...) to the class `IShape` just by adding a new visitor.

Cons:

• Adding a new concrete shape (`Triangle`, ...) requires to modifying all visitors.

The alternative of putting all functionalities as `virtual` methods in `IShape` has opposite pros and cons: Adding new functionality requires to modify all existing shapes, but adding a new shape doesn't impact existing classes. PDF - Download Design patterns for free
{"ft_lang_label":"__label__en","ft_lang_prob":0.5559322,"math_prob":0.8536312,"size":3281,"snap":"2021-31-2021-39","text_gpt3_token_len":797,"char_repetition_ratio":0.16936222,"word_repetition_ratio":0.15531915,"special_character_ratio":0.2627248,"punctuation_ratio":0.24035087,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9715058,"pos_list":[0,1,2],"im_url_duplicate_count":[null,null,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-09-18T14:14:58Z\",\"WARC-Record-ID\":\"<urn:uuid:61b83c96-e2f8-4488-9fe9-5d2ea9b5980b>\",\"Content-Length\":\"37071\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:260e65d7-4093-448e-a35a-e86b5e42c3b8>\",\"WARC-Concurrent-To\":\"<urn:uuid:7df3e1fc-6f2c-4537-8ee3-2927236313eb>\",\"WARC-IP-Address\":\"40.83.160.29\",\"WARC-Target-URI\":\"https://riptutorial.com/design-patterns/example/15127/visitor-pattern-example-in-cplusplus\",\"WARC-Payload-Digest\":\"sha1:6WQ5BDOALOJT5SHOATM4GABC2UUAMBAG\",\"WARC-Block-Digest\":\"sha1:CWQXOWX2B7ACZJNTQ3GSJQPP3X3LVLZC\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-39/CC-MAIN-2021-39_segments_1631780056476.66_warc_CC-MAIN-20210918123546-20210918153546-00306.warc.gz\"}"}