Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple classes in a header file vs. a single header file per class

People also ask

Should each class have its own header file?

Each class shall have it's own header and implementation file. So if we wrote a class called MyString we would need an associated MyStringh.

What is an advantage of using separate files for classes?

It is nice to avoid an extra set of naming conventions, by making each file name consistent with a C++ namespace or class names one avoids the need to think up new names or convert from one convention to another.

Can I have multiple classes in one cpp file?

In C++ you can define multiple classes inside of a single file. You will not run into trouble by doing it.

Can we have two classes in the same file?

Yes, it can. However, there can only be one public class per . java file, as public classes must have the same name as the source file. One Java file can consist of multiple classes with the restriction that only one of them can be public.


The term here is translation unit and you really want to (if possible) have one class per translation unit ie, one class implementation per .cpp file, with a corresponding .h file of the same name.

It's usually more efficient (from a compile/link) standpoint to do things this way, especially if you're doing things like incremental link and so forth. The idea being, translation units are isolated such that, when one translation unit changes, you don't have to rebuild a lot of stuff, as you would have to if you started lumping many abstractions into a single translation unit.

Also you'll find many errors/diagnostics are reported via file name ("Error in Myclass.cpp, line 22") and it helps if there's a one-to-one correspondence between files and classes. (Or I suppose you could call it a 2 to 1 correspondence).


Overwhelmed by thousands lines of code?

Having one set of header/source files per class in a directory can seem overkill. And if the number of classes goes toward 100 or 1000, it can even be frightening.

But having played with sources following the philosophy "let's put together everything", the conclusion is that only the one who wrote the file has any hope to not be lost inside. Even with an IDE, it is easy to miss things because when you're playing with a source of 20,000 lines, you just close your mind for anything not exactly refering to your problem.

Real life example: the class hierarchy defined in those thousand lines sources closed itself into a diamond-inheritance, and some methods were overridden in child classes by methods with exactly the same code. This was easily overlooked (who wants to explore/check a 20,000 lines source code?), and when the original method was changed (bug correction), the effect was not as universal as excepted.

Dependancies becoming circular?

I had this problem with templated code, but I saw similar problems with regular C++ and C code.

Breaking down your sources into 1 header per struct/class lets you:

  • Speed up compilation because you can use symbol forward-declaration instead of including whole objects
  • Have circular dependencies between classes (§) (i.e. class A has a pointer to B, and B has a pointer to A)

In source-controlled code, class dependencies could lead to regular moving of classes up and down the file, just to make the header compile. You don't want to study the evolution of such moves when comparing the same file in different versions.

Having separate headers makes the code more modular, faster to compile, and makes it easier to study its evolution through different versions diffs

For my template program, I had to divide my headers into two files: The .HPP file containing the template class declaration/definition, and the .INL file containing the definitions of the said class methods.

Putting all this code inside one and only one unique header would mean putting class definitions at the begining of this file, and the method definitions at the end.

And then, if someone needed only a small part of the code, with the one-header-only solution, they still would have to pay for the slower compilation.

(§) Note that you can have circular dependencies between classes if you know which class owns which. This is a discussion about classes having knowledge of the existence of other classes, not shared_ptr circular dependencies antipattern.

One last word: Headers should be self-sufficients

One thing, though, that must be respected by a solution of multiple headers and multiple sources.

When you include one header, no matter which header, your source must compile cleanly.

Each header should be self-sufficient. You're supposed to develop code, not treasure-hunting by greping your 10,000+ source files project to find which header defines the symbol in the 1,000 lines header you need to include just because of one enum.

This means that either each header defines or forward-declare all the symbols it uses, or include all the needed headers (and only the needed headers).

Question about circular dependencies

underscore-d asks:

Can you explain how using separate headers makes any difference to circular dependencies? I don't think it does. We can trivially create a circular dependency even if both classes are fully declared in the same header, simply by forward-declaring one in advance before we declare a handle to it in the other. Everything else seems to be great points, but the idea that separate headers facilitate circular dependencies seems way off

underscore_d, Nov 13 at 23:20

Let's say you have 2 class templates, A and B.

Let's say the definition of class A (resp. B) has a pointer to B (resp. A). Let's also say the methods of class A (resp. B) actually call methods from B (resp. A).

You have a circular dependency both in the definition of the classes, and the implementations of their methods.

If A and B were normal classes, and A and B's methods were in .CPP files, there would be no problem: You would use a forward declaration, have a header for each class definitions, then each CPP would include both HPP.

But as you have templates, you actually have to reproduce that patterns above, but with headers only.

This means:

  1. a definition header A.def.hpp and B.def.hpp
  2. an implementation header A.inl.hpp and B.inl.hpp
  3. for convenience, a "naive" header A.hpp and B.hpp

Each header will have the following traits:

  1. In A.def.hpp (resp. B.def.hpp), you have a forward declaration of class B (resp. A), which will enable you to declare a pointer/reference to that class
  2. A.inl.hpp (resp. B.inl.hpp) will include both A.def.hpp and B.def.hpp, which will enable methods from A (resp. B) to use the class B (resp. A).
  3. A.hpp (resp. B.hpp) will directly include both A.def.hpp and A.inl.hpp (resp. B.def.hpp and B.inl.hpp)
  4. Of course, all headers need to be self sufficient, and protected by header guards

The naive user will include A.hpp and/or B.hpp, thus ignoring the whole mess.

And having that organization means the library writer can solve the circular dependencies between A and B while keeping both classes in separate files, easy to navigate once you understand the scheme.

Please note that it was an edge case (two templates knowing each other). I expect most code to not need that trick.


We do that at work, its just easier to find stuff if the class and files have the same name. As for performance, you really shouldn't have 5000 classes in a single project. If you do, some refactoring might be in order.

That said, there are instances when we have multiple classes in one file. And that is when it's just a private helper class for the main class of the file.


+1 for separation. I just came onto a project where some classes are in files with a different name, or lumped in with another class, and it is impossible to find these in a quick and efficient manner. You can throw more resources at a build - you can't make up lost programmer time because (s)he can't find the right file to edit.


In addition to simply being "clearer", separating classes into separate files makes it easier for multiple developers not to step on each others toes. There will be less merging when it comes time to commit changes to your version control tool.


Most places where I have worked have folowed this practice. I've actually written coding standards for BAE (Aust.) along with the reasons why instead of just carving something in stone with no real justification.

Concerning your question about source files, it's not so much time to compile but more an issue of being able to find the relevant code snippet in the first place. Not everyone is using an IDE. And knowing that you just look for MyClass.h and MyClass.cpp really saves time compared to running "grep MyClass *.(h|cpp)" over a bunch of files and then filtering out the #include MyClass.h statements...

Mind you there are work-arounds for the impact of large numbers of source files on compile times. See Large Scale C++ Software Design by John Lakos for an interesting discussion.

You might also like to read Code Complete by Steve McConnell for an excellent chapter on coding guidelines. Actualy, this book is a great read that I keep coming back to regularly


It's common practice to do this, especially to be able to include .h in the files that need it. Of course the performance is affected but try not to think about this problem until it arises :).
It's better to start with the files separated and after that try to merge the .h's that are commonly used together to improve performance if you really need to. It all comes down to dependencies between files and this is very specific to each project.