This is probably subjective, but it's an interesting question. A class in C++ is used to represent several distinct concepts:
- An interface
- An object
- A type
An interface will involve virtual void foo() = 0
and (hopefully) no implementation. An object will bundle some state with some related methods, e.g. std::vector<int>
. A type is used to control the compilation process, but has no purpose beyond this - it could be as simple as struct tag;
or struct tag {}
.
I believe that whether the class and methods should be split depends on which of the above categories you are using it for. An interface will move everything it can into the source file. An object is likely to be a mixture of small inline methods, written in the header, and larger functions, perhaps with dependencies, in the source. A pure type tends to be involved with templates and entirely in the header.
All that said, most forms of "best practice" amount to (compromises between) minimising duplication and minimising coupling. If we apply these goals to classes, we probably want to put any method that would pull in dependencies from elsewhere into the source file to minimise coupling, and any others into the header so we don't need to type quite so much. Writing a class entirely in a source file is great until it needs to be shared with other compilation units, but until then, go for it.
This is complicated by templates. If the class in question is templated, one is forced to choose between writing most of it in the header or explicitly instantiating it for a known set of types in a single source file. I couldn't defend it as best practice, but I tend to write templated classes entirely in header files, factoring out such type-agnostic code as exists into free functions.