You may have noticed that during compilation the compiler only compiles .cpp files (not .h files).
When the compiler sees an #include statement, it literally inserts the .h file contents in that place, doing so recursively until all files are included (meaning it will also include every .h file included by the .h file and so on).
Eventually, the compiler ends up with a large .cpp file containing the original code plus all the included files on top of it.
This compilation step is called “preprocessing” and is also the time when all the macros are evaluated. Generally, instructions starting with ‘#’ are processed during the preprocessor step and are called “preprocessor directives”.
For example, to prevent including the same file multiple times, “one time include guards” are used in the form of
#ifndef SOMETHING_DOT_H
#define SOMETHING_DOT_H
//File contents
#endif
The #ifndef is a preprocessor directive (“if not defined”) and is evaluated during the preprocessor step.
So anyway, back to your question.
MainWindow.cpp has one include statement:
#include "JuceDemoHeader.h"
If you look inside it, you’ll notice that it expands into
#include "../JuceLibraryCode/JuceHeader.h"
#include "MainWindow.h"
#include "DemoUtilities.h"
You can see that JuceHeader.h is included here, which contains all the JUCE classes, like DocumentWindow and AsyncUpdater.
This is why these are available without explicitly including them from the MainWindow.h file - they’ve already been included from the .cpp file.
This is a very incomplete (and wrong) explanation and I suggest that you do some more reading on C++.
Happy Coding !