Hi all,
I've just started using C++ (from Python/Java), I'm trying to implement a basic visitor design pattern to be recursively used on a tree data structure.
I've got two methods in my mind but am unsure about what would be better.
The first is to define a degenerate Visitor class, containing only a virtual destructor:
1 2 3 4 5
|
class Visitor
{
public:
virtual ~Visitor() = 0;
}
|
Then, define a Visitable interface:
1 2 3 4 5
|
class Visitable
{
public:
virtual void accept(Visitor& visitor) = 0;
}
|
Now, any node in my data structure that I want to be visitable will inherit from the Visitable interface, and I will create an implementation of Visitor for that specific node, and use a dynamic_cast to cast the Visitor to the derived Visitor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
class MyNode : public Visitable
{
public:
void accept(Visitor& visitor)
{
if (MyNodeVisitor* myNodeVisitor = dynamic_cast<MyNodeVisitor*>(&visitor))
{
myNodeVisitor->visit(this);
}
}
}
class MyNodeVisitor : public Visitor
{
public:
void visit(MyNode& node)
{
// do stuff on node
}
}
|
So with this method I would need to create a visitor for each type of visitable node, however I could use generics to eliminate that, but keeping things simple for now. A concern of mine is the overhead of using a dynamic_cast. Especially as for my little project performance is really important.
The next thing I could do is change the Visitable class to have a method for every node type that returns itself as that type, OR returns 0 if its not that type, such as:
1 2 3 4 5 6 7 8
|
class Visitable
{
public:
virtual void accept(Visitor& visitor) = 0;
virtual MyNode* getMyNode() { return 0; }
virtual MyOtherNode* getMyOtherNode() { return 0; }
}
|
Then the MyNode class would override the 'getMyNode' function and return itself, but would NOT override the MyOtherNode method, thus it would return 0 if called on MyNode. Then we would update the classes to the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
class Visitor
{
public:
virtual void visit(Visitable& node) = 0;
}
class MyNode : public Visitable
{
public:
void accept(Visitor& visitor)
{
visitor->visit(this)
}
MyNode* getMyNode() override
{
return this;
}
}
class MyNodeVisitor : public Visitor
{
public:
void visit(Visitable& node) override
{
if(MyNode* myNode = node.getMyNode())
{
// do stuff
}
}
}
|
I'd like to know peoples thoughts on both methods, I'm concerned about the overhead of dynamic_cast but it seems to be a cleaner solution, however for the sake of writing a few extra functions in the Visitable class I feel it may be worth it. Also there are probably a million typos in my code, I wrote it in here and I can't preview for some reason.
Thanks!