Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Double Dispatch with an Inverted Visitor Pattern


May 1998/Double Dispatch with an Inverted Visitor Pattern/Listing 2

Listing 2: Test run of inverted visitor technique

////////// event.h
#include <iostream.h>
#include "widget.h"

class Event
{
public:
    virtual void visit(Widget& w) { w.handleEvent(*this); }
};

class EventA : public Event
{
public:
    void visit(Widget& w) { w.handleEvent(*this); }
};

class EventB : public Event
{
public:
    void visit(Widget& w) { w.handleEvent(*this); }
};

class EventC : public EventB
{
public:
    void visit(Widget& w) { w.handleEvent(*this); }
};

///////// widget.h

#include <iostream.h>

class Event;
class EventA;
class EventB;
class EventC;

class Widget
{
public:
    virtual void handleEvent(Event&)
    { cerr << "Widget, Event" << endl;  }
    virtual void handleEvent(EventA&)
    { cerr << "Widget, EventA" << endl; }
    virtual void handleEvent(EventB&)
    { cerr << "Widget, EventB" << endl; }
    virtual void handleEvent(EventC& c)
    { cerr << "Widget, EventC" << endl;
      handleEvent((EventB&)c);      }
};

class WidgetA : public Widget
{
public:
    void handleEvent(EventA&) { cerr << "WidgetA, EventA" << endl; }
    void handleEvent(EventB&) { cerr << "WidgetA, EventB" << endl; }
};

class WidgetB : public Widget
{
public:
    void handleEvent(EventB&) { cerr << "WidgetB, EventB" << endl; }
    void handleEvent(EventC&) { cerr << "WidgetB, EventC" << endl; }
};

class WidgetC : public WidgetB
{
public:
    void handleEvent(EventB&)
    { cerr << "WidgetC, EventB" << endl; }
    // void handleEvent(EventC&)
    // { cerr << "WidgetC, EventC" << endl; }
};

//////// main.c

#include "event.h"

void myVisitEngine(Widget& w, Event& e) { e.visit(w); }

int main()
{
    WidgetA wa;

    WidgetB wb;
    WidgetC wc;
    EventA ea;
    EventB eb;
    EventC ec;
    Widget *eh = &wa;

    cerr << "-------------" << endl;
    cerr << "-------------" << endl;

    eh->handleEvent(ea);
    wa.handleEvent(ea);

    cerr << "-------------" << endl;

    eh->handleEvent(eb);
    ((Widget&)wa).handleEvent(eb);

    cerr << "-------------" << endl;

    eh->handleEvent(ec);
    wa.handleEvent(ec);

    cerr << "-------------" << endl;
    cerr << "-------------" << endl;

    eh = &wb;
    eh->handleEvent(ea);
    ((Widget&)wb).handleEvent(ea);

    cerr << "-------------" << endl;

    eh->handleEvent(eb);
    wb.handleEvent(eb);

    cerr << "-------------" << endl;

    eh->handleEvent(ec);
    wb.handleEvent(ec);

    cerr << "-------------" << endl;
    cerr << "-------------" << endl;

    eh = &wc;
    eh->handleEvent(ea);
    ((Widget&)wc).handleEvent(ea);

    cerr << "-------------" << endl;

    eh->handleEvent(eb);
    wc.handleEvent(eb);

    cerr << "-------------" << endl;

    eh->handleEvent(ec);
    wc.handleEvent(ec);

    cerr << "-------------" << endl;
    cerr << "-------------" << endl;

    myVisitEngine(wa,ea);
    myVisitEngine(wa,eb);
    myVisitEngine(wa,ec);

    cerr << "-------------" << endl;

    myVisitEngine(wb,ea);
    myVisitEngine(wb,eb);
    myVisitEngine(wb,ec);

    cerr << "-------------" << endl;

    myVisitEngine(wc,ea);
    myVisitEngine(wc,eb);
    myVisitEngine(wc,ec);

    cerr << "-------------" << endl;
    cerr << "-------------" << endl;

    return 1;

}

//////// Output
-------------
-------------     // Each Widget is asked to handle each different
                  // event in turn
WidgetA, EventA   // <-- First through a base class pointer
                  //     to the Widget
WidgetA, EventA   // <-- Then through a direct reference
-------------
WidgetA, EventB
WidgetA, EventB
-------------
Widget, EventC    // <-- Here since WidgetA has no handler for
                  //     EventC (which derives from EventB),
WidgetA, EventB   //     it falls through to the base class, which
                  //     then reroutes to the EventB handler
WidgetA, EventB
-------------
-------------
Widget, EventA    // <-- Since WidgetB has no EventA handler,
Widget, EventA    //     it falls back to base the class
                  //     implementation 
-------------
WidgetB, EventB
WidgetB, EventB
-------------
WidgetB, EventC
WidgetB, EventC
-------------
-------------
Widget, EventA    // <-- WidgetC has no EventA handler either
Widget, EventA
-------------
WidgetC, EventB
WidgetC, EventB
-------------
WidgetB, EventC   // <-- This is an example of the different
WidgetC, EventB   //     behavior from using a base class pointer
                  //     and a direct reference, when the EventC
                  //     handler does not exist.
-------------
-------------     // Now a generic visitation engine is simulated,
                  // which asks the event to visit the widget
WidgetA, EventA
WidgetA, EventB
Widget, EventC    // <-- Same behavior as above for
                  //     WidgetA and EventC
WidgetA, EventB
-------------
Widget, EventA
WidgetB, EventB
WidgetB, EventC
-------------
Widget, EventA
WidgetC, EventB 
WidgetB, EventC   // <-- A generic base class engine will generate
                  //     this behavior.
-------------
-------------
/* End of File */

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.