Visitor Pattern
But, I wouldn't want to have a Node.printType function that prints its type and also recursively traverses its children to print their types.
The visitor pattern does exactly this. Conceptually, it allows for a virtual function to be added to an entire class hierarchy, without having to put the function within the class hierarchy itself. Below is a
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Asteroid;
class MyAsteroid;
class IAsteroidVisitor
{
public:
    virtual void visit(Asteroid&) = 0;
    virtual void visit(MyAsteroid&) = 0;
};
class Asteroid
{
public:
    virtual string getType()
    {
        return "Asteroid";
    }
    virtual void accept(IAsteroidVisitor& visitor)
    {
        visitor.visit(*this);
    }
    
};
class MyAsteroid : public Asteroid
{
public:
    string getType() override
    {
        return "My Asteroid";
    }
    string doFunkyStuff()
    {
        return "I do something the normal asteroid can't!";
    }
    void accept(IAsteroidVisitor& visitor) override
    {
        visitor.visit(*this);
    }
};
class AsteroidList
{
private:
    list<Asteroid*> m_pAsteroidList;
public:
    AsteroidList()
    {
        m_pAsteroidList.push_back(new Asteroid());
        m_pAsteroidList.push_back(new MyAsteroid());
    }
    void accept(IAsteroidVisitor& visitor)
    {
        for (list<Asteroid*>::const_iterator i = m_pAsteroidList.cbegin(); i != m_pAsteroidList.cend(); i++)
        {
            (*i)->accept(visitor);
        }
    }
};
class AsteroidPrintVisitor : public IAsteroidVisitor
{
public:
    void visit(Asteroid& a) override
    {
        cout<<a.getType()<<endl;
    }
    void visit(MyAsteroid &ma) override
    {
        cout<<ma.getType()<<endl;
        cout<<ma.doFunkyStuff()<<endl;
    }
};
int main(int argc, char *argv[])
{
    AsteroidList al;
    AsteroidPrintVisitor p;
    al.accept(p);
    return 0;
}Labels: design pattern, double-dispatch

