An #include directive tells the compiler to, quite literally, copy-paste the specified header file into the file that is including it, without any second thought.
The problem occurs when one file includes another file twice. Because it simply copy-pastes, all code in that header file is now doubled up in the including file. If you ever tried declaring the same function or class twice, then you know that the compiler will throw errors around if you do this.
You might think "Well, I'm not an idiot, I'll just make sure not to include the same file twice!", but the problem gets harder when one file includes two files, and one of those two includes the other. Add to that the fact that standard headers often include other headers, and you've got yourself a disaster waiting to happen.
Rather than having to figure out an inclusion-tree, so that each file is only included once, yet each file has access to the includes it needs, we use header guards.
Using header guards, you basically tell the compiler "this has already been included, so skip the contents". It does so by a define macro, which is then checked. If it is already defined, the compiler skips the rest of the file. Of course, the only way it can be defined is if this file has already been included. That's why it's often easiest to have the #define parameter be something related to the filename. Since filenames must be unique, so will the define parameter.
#include "B.h"
#include "C.h"
int main()
{
B myMainB;
C myMainC;
}
The user needs to include both B.h and C.h. Both header files include A.h. If there were no include guards (as in this example), class A would be defined twice. The include guard would prevent the definition of A a second time.