-1

I implemented a visitor design pattern. I want to eliminate the circular header includes. The code below is working, g++ compile it.

I have a file: Classes.h It has base and derived class declaration, also has Classes.cpp with the definitions of methods.

Classes.h:

#include "VisitorDesignPattern/Visitor.h"

class Visitor;
class DerivedVisitorA;
class DerivedVisitorB;

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

class DerivedA : public Base
{
    public:
        void accept(Visitor &v);
};

class DerivedB : public Base
{
    public:
        void accept(Visitor &v);
};

Classes.cpp contains the definitions, definitons of accept method, as well, as I mentioned.

Visitor.h:

#include "../Classes.h"

class Base;
class DerivedA;
class DerivedB;

class Visitor
{
    public:
        virtual void Visit(DerivedA &derivedA) = 0;
        virtual void Visit(DerivedB &derivedB) = 0;
};

class DerivedVisitorA : public Visitor
{
    public:
        void Visit(DerivedA &derivedA);
        void Visit(DerivedB &derivedB);
};

class DerivedVisitorB : public Visitor
{
    public:
        void Visit(DerivedA &derivedA);
        void Visit(DerivedB &derivedB);
};

Visitor.cpp contains the definition of methods.

I am using this in every .h file:

#ifndef VISITOR_H
#define VISITOR_H
...
#endif

#ifndef CLASSES_H
#define CLASSES_H
...
#endif

So in this case how can I eliminate the circular header includes?

Business Man
  • 81
  • 1
  • 6
  • This question has been answered before – Taekahn Apr 02 '22 at 19:36
  • Where? Can you give me the url, please? – Business Man Apr 02 '22 at 19:43
  • https://stackoverflow.com/search?q=%5Bc%2B%2B%5D+circular – Taekahn Apr 02 '22 at 19:45
  • 1
    Neither one of those headers depends on the contents of the other. So just remove the `#include` directives from the two headers. – Pete Becker Apr 02 '22 at 19:53
  • @PeteBecker I removed it, now I get a lot of compiler errors. – Business Man Apr 02 '22 at 20:24
  • @BusinessMan -- so, you fixed the problem you asked about, and now you're getting errors in code that you haven't shown? What's wrong with this picture? – Pete Becker Apr 02 '22 at 21:49
  • @PeteBecker The problem what I posted is compile with g++ with no errors, but it contains circular header includes, and I want to remove it. Did you read the first line of this question? "I implemented a visitor design pattern. I want to eliminate the circular header includes. The code below is working, g++ compile it." – Business Man Apr 02 '22 at 22:08
  • Your code has two offsetting errors. You fixed one (the circular includes) and that exposed the other. Now it's time to fix the other. – Pete Becker Apr 03 '22 at 14:44

1 Answers1

0

In your example, you don't need to include the other header in either of them.

You only need to declare types that you mention and define the ones that you use. Having a type pointer/reference in a function signature is not using it. Accessing said type's fields (explicitly or implicitly) or metadata (size, alignment, etc.), as I assume you would do inside Visitor::Visit(), is.

// Only a declaration. At this point the compiler doesn't know anythng about this type.
struct A;

// Doesn't compile, because B has an implicit default constructor, which the compiler can't generate, because it doesn't know about A's constructor.
// struct B { A member; };

// Compiles, because because the size of a pointer (a reference) is the same for all types.
struct C { A& member; };

// Compiles, since it's only a definition - no code is generated.
void f1(A);

// Doesn't compile, because the compiler needs to know the size of a function's arguments to generate code.
// void f2(A) {}

// Compiles, because the size of a pointer (a reference) is the same for all types.
void f3(A&) {}

// Doesn't compile, because A::foo() hasn't been declared
// void f4(A& a) { a.foo(); }

// A declaration. Now the compiler knows the size of this class and its members.
struct A {
    void foo();
    void bar() {};
};

// A definition for the previously declared f1(), compiles becase A is complete type
void f1(A a) { a.bar(); }

// Compiles, but produces a linker error because it can't find the definition for A::foo()
// void f4(A& a) { a.foo(); }

void A::foo() {}

// Compiles and links
void f4(A& a) { a.foo(); }
Roman
  • 70
  • 1
  • 6
  • If I do not include headers - circular way - I get a lot of compiler error. Your example does not help me at my actual context. – Business Man Apr 02 '22 at 20:25