include guards(both #ifndef and #pragma) doesn't work across compilation units, which is one of the reasons you should never ever ever define anything in a header file, only declare them. Except for templates of course.
A compilation unit is one .cpp-file and all included headers. Each .cpp create an object file containing a middle stage binary representation of the code, this is the compilation stage. These object files are then linked together in the linking stage. Since each .cpp is handled separately in c++ if you have "float foo;" in header.hpp and both a.cpp and b.cpp include header.hpp, how would the compiler know which foo you mean when running the application?