Search code examples
c++code-organizationvisitor-pattern

Code organizing


I have this visitor pattern implementation:

class Visitor {
  public:
    Visitor() {}
    void visit(A *a){ a->doSomething(); }
    void visit(B *b){ b->doSomething(); }
};

class Base {
  public:
    Base() {}
    virtual void accept(Visitor *v) = 0;
};

class A: public Base {
  public:
    A():Base() {}
    void accept(Visitor *v) override { v->visit(this) };
    .....
};

class B: public Base {
  public:
    B():Base() {}
    void accept(Visitor *v) override { v->visit(this) };
};

The problem is that A and B have incomplete types in the Visitor implementation. But I don't want to put implementation in a separate source file.

Is there a way to put it in a single header file?


Solution

  • Do forward declaration A and B. Move your visit(A*a); and visit(B*b); outside of Visitor's class declaration and declare it after A and B classes. To avoid duplicate symbols put this to header file, for example Header.h:

    //forward declarations
    class A;
    class B;
    
    class Visitor {
    public:
        Visitor() {}
        void visit(A *a);
        void visit(B *b);
    };
    
    class Base {
    public:
        Base() {}
        virtual void accept(Visitor *v) = 0;
    };
    
    class A: public Base {
    public:
        A():Base() {}
        void accept(Visitor *v) override { v->visit(this); };
        void doSomething(){};
    };
    
    class B: public Base {
    public:
        B():Base() {}
        void accept(Visitor *v) override { v->visit(this); };
        void doSomething(){};
    };
    

    This declaration should be putted in cpp file, to avoid duplicate symbols, for example add it to main.cpp:

    #include "Header.h"
    
    //outside declarations of methods
    void Visitor::visit(A *a){ a->doSomething(); }
    void Visitor::visit(B *b){ b->doSomething(); }