Yes, it does. However, C++ supports function overloading. That is the same function can be called with different arguments. How do you suppose the compiler knows which code to actually execute when you type Serial.print(val);?
The answer is that every function really gets a different name. That name is made up of the function name and the types of the arguments that the function accepts.
So, Serial.print() for an int is a different name what Serial.print() for a float.
The C++ compiler is looking for a function based on the name and the arguments that the function accepts.
The C compiler, because it does not support function overloading, knows that the function name is unique, so it doesn't mangle the name.
The linker, then, can't find the mangled name it is looking for in the object file produced by the C compiler.
I changed the files to .cpp and it worked. What I still dont understand is why ? If my project is completely in C or C++ then the linker should be able to handle it. What you describe should cause problems when i mix C and C++ together, if I understood you correctly.