I was trying out some c++ code while working with classes and this question occurred to me and it’s bugging me a little.
I have created a header file that contains my class definition and a cpp file that contains the implementation.
If I use this class in a different cpp file, why am I including the header file instead of the cpp file that contains the class implementations?
If I include the class implementation file, then the class header file should be imported automatically right (since i’ve already included the header file in the implementation file)? Isn’t this more natural?
Sorry if this is a dumb question, i’m genuinely interested in knowing why most people include .h instead of .cpp files when the latter seems more natural (I know python somewhat, maybe that’s why it seems natural to me atleast). Is it just historical or is there a technical reason concerning program organisation or maybe something else?
Because when you’re compiling another file, C++ doesn’t actually need to know about the implementation. It only needs to know the signature of each function (which paramters it takes and what it returns), the name of each class, what macros are
#defined, and other “summary” information like that, so that it can check that you’re using functions and classes correctly. The contents of different.cppfiles don’t get put together until the linker runs.For example, say you have
foo.hand
foo.cppand
bar.cppWhen you compile
foo.cpp, it becomesfoo.o, and when you compilebar.cpp, it becomesbar.o. Now, in the process of compiling, the compiler needs to check that the definition of functionfoo()infoo.cppagrees with the usage of functionfoo()inbar.cpp(i.e. takes anintand afloatand returns anint). The way it does that is by making you include the same header file in both.cppfiles, and if both the definition and the usage agree with the declaration in the header, then they must agree with each other.But the compiler doesn’t actually include the implementation of
foo()inbar.o. It just includes an assembly language instruction tocall foo. So when it createsbar.o, it doesn’t need to know anything about the contents offoo.cpp. However, when you get to the linking stage (which happens after compilation), the linker actually does need to know about the implementation offoo(), because it’s going to include that implementation in the final program and replace thecall fooinstruction with acall 0x109d9829(or whatever it decides the memory address of functionfoo()should be).Note that the linker does not check that the implementation of
foo()(infoo.o) agrees with the use offoo()(inbar.o) – for example, it doesn’t check thatfoo()is getting called with anintand afloatparameter! It’s kind of hard to do that sort of check in assembly language (at least, harder than it is to check the C++ source code), so the linker relies on knowing that the compiler has already checked that. And that’s why you need the header file, to provide that information to the compiler.