Your analysis is basically correct... all the included files are expanded in place and the resultant code - a translation unit - is compiled into an object, library or application.
Still, any non-trivial projects relies on symbols (variables, functions) defined in other libraries, even if only for things like malloc(), socket(), file(), write() etc. provided by the language's or operating system's standard libraries. Even if you don't call them directly, they're needed by the implementation of things like new and iostream.
When your own project gets bigger, you'll also want to divide your functionality into different objects or libraries, as that makes the functionality more re-usable, independently testable, and means that after some code change you can recompile only those objects invalidated by the change then relink - which can be massively faster than recompiling every single bit of code in your entire project.
Your C++ compiler creates objects (which may or may not have the extra interfacing and code to make them libraries or applications) from translation units - which are the concatenations of includes and cpp file you've mentioned - possibly importing and combining that with symbols from existing static libraries or other objects you've mentioned on the compiler command line.
For each of these independent objects, the compiler needs to be able to tell new code how to access and use the contained symbols; the header files serve this purpose, advertising the available object content.
Implementation (cpp) files should almost always include their header file first because the compiler will then complain if there is some discrepency between the object content it is building and the header-file-advertised content that code using the object will later expect. For some things - like classes, a class declaration must be seen before the member function implementation can be specified, and given the class declaration is needed by client code and therefore in the header, in practice the implementation needs to include the header too. (I say a cpp should include its header first because the compiler will then complain if the header relies on some content that it doesn't include itself. Otherwise, if say the cpp includes the std::string header and the header uses it, but some other client code tries to include the header without having included string, then the compilation will fail).
Implementation files could include other implementation files, but that wouldn't fit in with the general division of compilation described above, so would confuse people used to this convention.