When I work on a project, I make only one .h file and one .cpp file. It seems it doesn't cause problems.
If you have only one .cpp file, then you do not need the header file. The header file is only needed to tell the compiler about entities which are declared outside the current cpp file (the can be in another .cpp, .obj, .lib or .dll).
That said, there are several reasons to split code:
- readability. Hunting down the needed function is much easier in a 1K lines module than in a 100K lines monstrosity. That becomes even easier, if you organize your project so that you can tell the module name by looking at the function / object name. For example, if you have a set of functions for working with foobar, then it is logical to name functions foobar_create(), foobar_destroy() etc. and put them all in a module named foobar.c.
- partial recompilation. If your project has 10K lines of code split into 10 files, and if you change a single line, then the compiler only has to recompile one file (1K lines) instead of recompiling everything. Much faster.
- decrease in coupling. This one is non-obvious, so I wil take some time explaining it.
Imagine that your project involves manipulating foos and bars. Now, if you mix handling foos and bars in one file, then it becomes tempting to add code messing with bars into functions handling foos and vice versa. That looks like a good idea, but after a while your code will become an unreadable (and undebuggable) spaghetti, because it will be impossible to tell how foos and bars interoperate.
However, if you put all the foo stuff in foo.cpp and all the bar stuff in bar.cpp, then in order to manipulare bars from foo.cpp, you must first export the interface to do so by declaring it in bar.h. And that's the point: the bar.h becomes a list of things that foo.cpp can do with bars. Consequently, you can tell what you can change in internal workings of functions handling bars, without breaking operation of foo.cpp. Try that without having explicitly declared the interface!