Multiple classes in the header file versus one header file for each class

For some reason, our company has a coding guide that states:

Each class shall have it own header and implementation file.

So, if we wrote a class called MyString , we will need the associated MyStringh.h and MyString.cxx .

Does anyone else do this? Has anyone seen any compromise results as a result? Does 5,000 classes in 10,000 files be as fast as 5,000 classes in 2,500 files? If not, is the difference noticeable?

[We encode C ++ and use GCC 3.4.4 as our daily compiler]

+55
c ++ performance file-organization
Aug 26 '08 at 14:19
source share
12 answers

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

This is usually a more efficient (from the point of view of compilation / link) ability to do this, especially if you are doing things like incremental communication, etc. The idea is that translation units are isolated in such a way that when one translation unit changes, you don’t need to rearrange many things, as would be necessary if you started dumping many abstractions into one translation unit.

You will also find that many errors / diagnostics are reported through the file name ("Error in Myclass.cpp, line 22"), and this helps if there is a one-to-one correspondence between files and classes. (Or, I suppose, you could call it correspondence from 2 to 1).

+57
Aug 26 '08 at 14:34
source share

Crowded with thousands of lines of code?

Having one set of headers / source files for each class in a directory might seem redundant. And if the number of classes goes to 100 or 1000, it can even get scared.

But, playing with the sources, following the philosophy of “let's all together”, the conclusion is that only the one who wrote the file has some hope not to get lost inside. Even when working with the IDE, it’s easy to miss something, because when you play with a source of 20,000 lines, you simply close your mind to something that does not fit your problem.

Real life example: the class hierarchy defined in these thousands of sources has closed itself into diamond inheritance, and some methods have been redefined in child classes by methods with exactly the same code. This was easily missed (who wants to study / check 20,000 lines of source code?), And when the original method was changed (bug fixed), the effect was not as universal as the exception.

Dependencies getting round?

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

Destruction of sources in 1 heading for each structure / class allows you to:

  • Speed ​​up compilation because you can use the forward-declaration character 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 can cause classes to move up and down the file regularly, just to compile the header. You do not want to study the evolution of such movements when comparing the same file in different versions.

The presence of separate headers makes the code more modular, compiles faster and simplifies the study of its evolution using different versions of diffs

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

Putting all this code inside one and only one unique header would mean including class definitions at the beginning of this file and a method definition at the end.

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

(§) Note that you can have circular dependencies between classes if you know which class belongs to them. This is a discussion about classes that have knowledge about the existence of other classes, rather than round-robin circular dependencies shared_ptr.

Last word: headlines should be self-sufficient

One thing, however, must be respected by the decision of several headings and several sources.

When you include one header, no matter what the header, your source should compile cleanly.

Each title should be self-sufficient. You should develop the code, and not search for treasures, burn your project with more than 100,000 source files to determine which heading defines the character in the heading of 1000 lines, which you only need to include for just one listing.

This means that either each header defines, or forward-declare all the characters it uses, or includes all the necessary headers (and only the necessary headers).

Circular dependency issue

underscore-d asks:

Can you explain how using separate headers has any meaning for circular dependencies? I do not think so. We can trivially create a circular dependency, even if both classes are fully declared in the same header, just by forward declaration well in advance before declaring a handle to it in the other. Everything else seems to be great points, but the idea that individual headings facilitate circular dependencies seems empty.

underscore_d, November 13 at 11:20 p.m.

Say you have 2 class templates, A and B.

Say a class definition A (respectively B) has a pointer to B (respectively A). Let also methods of class A (respectively, B) actually call methods from B (respectively, A).

You have a cyclical dependency both in the definition of classes and in the implementation of their methods.

If A and B were normal classes, and methods A and B were in .CPP files, there would be no problem: you would use the forward declaration, have a header for each class definition, then each CPP would include as HPP.

But since you have the templates, you really need to reproduce these templates above, but only with the headers.

It means:

  • definition header A.def.hpp and B.def.hpp
  • implementation header A.inl.hpp and B.inl.hpp
  • for convenience, the “naive” headline of A.hpp and B.hpp

Each heading will have the following attributes:

  • In A.def.hpp (e.g. B.def.hpp) you have a direct declaration of class B (respectively A) that allows you to declare a pointer / link to this class
  • A.inl.hpp (e.g. B.inl.hpp) will include both A.def.hpp and B.def.hpp, which will allow methods from A (respectively B) to use class B (respectively A).
  • A.hpp (respectively B.hpp) will directly include both A.def.hpp and A.inl.hpp (respectively B.def.hpp and B.inl.hpp)
  • Of course, all headings should be self-contained and protected by heading defenders.

A naive user will include A.hpp and / or B.hpp, while ignoring the entire mess.

And the presence of this organization means that the librarian can resolve circular dependencies between A and B, saving both classes in separate files, it is easy to move around as soon as you understand the scheme.

Note that this was a boundary register (two patterns that know each other). I expect most code will not need this trick.

+55
Sep 19 '08 at 20:30
source share

We do this at work, it is simply easier to find material if the class and files have the same name. In terms of performance, you really shouldn't have 5,000 classes in one project. If you do, some refactoring might be fine.

However, there are examples when we have several classes in one file. And this is when it is just a private helper class for the main class of the file.

+10
Aug 26 '08 at 14:23
source share

In addition to the simple "clear" separation of classes into separate files, it is simplified for several developers not to step on each other. When it comes time to commit changes to your version control tool, there will be less merging.

+7
Aug 26 '08 at 14:34
source share

+1 for sharing. I just came to a project where some classes are in files with a different name or concentrated in another class, and they cannot be found quickly and efficiently. You can throw more resources at the assembly - you cannot lose the programmer’s time, because he cannot find the necessary file for editing.

+6
Aug 26 '08 at 14:28
source share

G'day

In most places where I worked, we followed this practice. I actually wrote coding standards for BAE (Aust.), As well as reasons why, instead of just carving something in stone without any real excuse.

As for your question about the source files, this is not much time to compile, but the problem is even more in finding the appropriate piece of code in the first place. Not everyone uses an IDE. And knowing that you're just looking for MyClass.h and MyClass.cpp, it really saves time compared to running "grep MyClass *. (H | cpp)" over a bunch of files, and then it filters out the #include MyClass.h ... instructions

Keep in mind that during compilation there are a large number of source file sources. See John Lakos's Large-scale C ++ Software Development for an interesting discussion.

You might also like to read Code Complete by Steve McConnell for an excellent chapter on coding guidelines. In fact, this book read very well that I constantly return to

amuses Rob

+5
Aug 26 '08 at 14:31
source share

Best practice, as others have said, is to put each class in its own translation unit in terms of maintenance and code understanding. However, on large systems, this is sometimes not recommended — see the section “Make these source files larger” in this article by Bruce Dawson for a discussion of trade-offs.

+3
Aug 27 '08 at 16:41
source share

This is common practice for this, especially for including .h in files that need it. Of course, performance is affected, but try not to think about this problem until it arises :).
It’s better to start with split files and then try to combine the .h, which 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 for each project.

+2
Aug 26 '08 at 14:25
source share

I found these guidelines especially helpful when it comes to header files: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Header_Files

+2
Dec 01 '10 at 22:29
source share

It is very useful to have only one class for each file, but if you do your construction through massive assembly files, which include all individual C ++ files, this makes compilation easier, since the startup time is relatively long for many compilers.

+1
Sep 18 '08 at 5:12
source share

I am surprised that almost everyone wants to have one file per class. The problem is that in the "refactoring" era, it can be difficult to keep file and class names in sync. Each time you change the class name, you also need to change the file name, which means that you must also make changes to all files.

I personally group the related classes into separate files, and then give this file a meaningful name that does not need to be changed, even if the class name is changed. Having fewer files makes it easier to scroll through the file tree. I use Visual Studio for Windows and Eclipse CDT on Linux, and both have shortcuts that immediately fall into the class declaration, so finding a class declaration is quick and easy.

Having said that, I think that as soon as the project is completed, or its structure has “hardened”, and name changes will become rare, it may make sense to have one class for each file. I want a tool that can extract classes and put them in separate .h and .cpp files. But I do not consider it necessary.

The choice also depends on the type of project he is working on. In my opinion, this question does not deserve a black and white answer, since any choice has its pros and cons.

+1
Jan 07 '15 at 14:33
source share

The same rule applies here, but it notes a few exceptions when allowed. In this way:

  • Inheritance trees
  • Classes that are used only within very .
  • Some utilities are simply placed in the generic 'utils.h'
0
Aug 26 '08 at 2:30 p.m.
source share



All Articles