Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You've currently got everything trying to include everything else. This will get you into trouble.</p> <p>It looks like Line2 needs to know about Vector2; and Circle2 needs to know about both Line2 and Vector2. Does Vector2 stand on its own, or does it try to use Line2 or Circle2?</p> <p>If it stands on its own, then you simply need to have Line2 include Vector2, and Circle2 include Line2 and Vector2. Then remove the other include statements that have you running around in circles (e.g. Circle2 includes geometry which includes Circle2...).</p> <p>If Vector2 tries to use Line2 or Circle2, you'll have a circular dependency. Here's how to solve that:</p> <ul> <li>remove the <code>#include</code> statements from the header files (just your geometry/Circle2/etc)</li> <li>forward declare the classes you need in each header (see Baget's answer)</li> <li>change the method signature to take a constant reference as a parameter (e.g. instead of taking <code>Line2</code>, take <code>const Line2&amp;</code>)</li> <li>in the source files, <code>#include</code> the header files of the shapes you need.</li> </ul> <p>The way this works is that the header files no longer have a dependency on the other shapes, so it breaks the circular include cycle. <code>Circle2.cpp</code> includes <code>Line2.h</code>, but <code>Line2.h</code> doesn't include <code>Circle2.h</code>, so the cycle ends there.</p> <p>Forward declaring the class tells the compiler "there is a class called <code>Line2</code>, but you don't need to know any details about it yet". Changing the methods to use references (or pointers) allows the compiler to not need any class details when processing the header.</p> <p>When the compiler processes the source (where you'll actually do something with the other class), it now needs to know the details of the other class. This is why you need to include the full class definition in the source file.</p> <p><strong>EDIT</strong>: a little more explanation about what happens with include guards and circular includes.</p> <p>I'll use the simplest case: A.h includes B.h and B.h includes A.h.</p> <p>When you attempt to compile A.obj, the preprocessor loads all the include statements, and basically does a cut-n-paste of the included file into the source file (and then hands the result to the compiler). So here's the order this will be processed:</p> <ul> <li>In <code>A.cpp</code>, it reaches <code>#include "A.h"</code>, where it jumps out of A.cpp, and loads A.h</li> <li>In <code>A.h</code>, it reaches <code>#ifndef A_H</code>. Since that's not set, it continues.</li> <li>In <code>A.h</code>, it reaches <code>#define A_H</code>. Now that's set.</li> <li>In <code>A.h</code>, it reaches <code>#include "B.h"</code>, where it jumps out of A.h, and loads B.h</li> <li>In <code>B.h</code>, it reaches the include guard for <code>B_H</code>, which wasn't set, and sets it.</li> <li>In <code>B.h</code>, it reaches <code>#include "A.h"</code>, where it jumps out of B.h and loads A.h (again)</li> <li>In <code>A.h</code>, it reaches <code>#ifdef A_H</code>. Since that <strong>IS</strong> set, it skips until <code>#endif</code> - at the end of the file.</li> <li>Back to <code>B.h</code>, preprocessing continues.</li> </ul> <p>So you can see here that <code>B.h</code> didn't even need to include <code>A.h</code>, since that did nothing anyway. But if you try to take it out, then B.obj won't compile. And when you try to compile B.obj, <code>A.h</code> doesn't need to include <code>B.h</code>. This leads to a weird scenario:</p> <ul> <li>when you compile <code>A.obj</code>, the compiler will see the declarations in <code>B.h</code> before <code>A.h</code>.</li> <li>when you compile <code>B.obj</code>, the compiler will see the declarations in <code>A.h</code> before <code>B.h</code>.</li> </ul> <p>In order for this to work, two things must be true:</p> <ul> <li>to compile <code>A.obj</code>, the compiler has to be able to compile <code>B.h</code> without <code>A.h</code> </li> <li>to compile <code>B.obj</code>, the compiler has to be able to compiler <code>A.h</code> without <code>B.h</code></li> </ul> <p>So, to build your whole project, A.h and B.h can't actually rely on including each other. This is where the importance of forward declarations comes into play. This is where you can tell B.h about <code>class A;</code> - without actually using the include statement. Of course you have to follow the rules for forward declarations - only references or pointers, no dereferencing.</p> <p>Note that if you add the forward declaration, without removing the <code>#include</code> statements, your project will build. Because (as I showed above), sometimes that <code>#include</code> statement does nothing.</p> <p>I hope that clears things up.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload