120

When dividing your code up into multiple files, what exactly should go into an .h file and what should go into a .cpp file?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Enrico Tuvera Jr
  • 2,739
  • 6
  • 35
  • 51
  • 1
    Related question: http://stackoverflow.com/questions/333889/in-c-why-have-header-files-and-cpp-files – Spoike Dec 22 '09 at 11:44
  • 9
    This is a pure style issue, but I believe that C++ declarations go in a `.hpp` file while C declarations go into a `.h` file. This is very helpful when mixing C and C++ code (for example legacy modules in C). – Thomas Matthews Dec 22 '09 at 13:29
  • 1
    @ThomasMatthews Makes sense. Is that practice oft used? – llf May 22 '18 at 01:42
  • 1
    @lightningleaf: Yes, the practice is oft used especially when mixing C++ and C languages. – Thomas Matthews May 22 '18 at 14:06

12 Answers12

145

Header files (.h) are designed to provide the information that will be needed in multiple files. Things like class declarations, function prototypes, and enumerations typically go in header files. In a word, "definitions".

Code files (.cpp) are designed to provide the implementation information that only needs to be known in one file. In general, function bodies, and internal variables that should/will never be accessed by other modules, are what belong in .cpp files. In a word, "implementations".

The simplest question to ask yourself to determine what belongs where is "if I change this, will I have to change code in other files to make things compile again?" If the answer is "yes" it probably belongs in the header file; if the answer is "no" it probably belongs in the code file.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • 4
    Except private class data has to go into the header. Templates must be completely header defined (unless you use one of the few compilers that supports `export`). The only way around #1 is PIMPL. #2 would be possible if `export` was supported and may be possible using c++0x and `extern` templates. IMO, header files in c++ lose much of their usefulness. – KitsuneYMG Dec 22 '09 at 12:39
  • 35
    All good, but with inaccurate terminology. In a word, "declarations" - the term "definition" is synonymous with "implementation". Only declarative code, inline code, macro definitions, and template code should be in a header; i.e. nothing that instantiates code or data. – Clifford Dec 22 '09 at 13:44
  • 9
    I have to agree with Clifford. You use the terms declaration and definition rather loosly and somewhat interchangably. But they have precise meanings in C++. Examples: A class declaration introduces a name of a class but doesn't say what's in it. A class definition lists all members and friend functions. Both can be put into header files without problems. What you call "function prototype" is a function *declaration*. But a function *definition* is that thing that contains the function's code and should be placed into a cpp-file -- unless it's inline or (part of) a template. – sellibitze Dec 22 '09 at 16:22
  • 6
    They have precise meanings in C++, they do not have precise meanings in English. My answer was written in the latter. – Amber Dec 22 '09 at 21:53
67

Fact is, in C++, this is somewhat more complicated that the C header/source organization.

What does the compiler see?

The compiler sees one big source (.cpp) file with its headers properly included. The source file is the compilation unit that will be compiled into an object file.

So, why are headers necessary?

Because one compilation unit could need information about an implementation in another compilation unit. So one can write for example the implementation of a function in one source, and write the declaration of this function in another source needing to use it.

In this case, there are two copies of the same information. Which is evil...

The solution is to share some details. While the implementation should remain in the Source, the declaration of shared symbols, like functions, or definition of structures, classes, enums, etc., could need to be shared.

Headers are used to put those shared details.

Move to the header the declarations of what need to be shared between multiple sources

Nothing more?

In C++, there are some other things that could be put in the header because, they need, too, be shared:

  • inline code
  • templates
  • constants (usually those you want to use inside switches...)

Move to the header EVERYTHING what need to be shared, including shared implementations

Does it then mean that there could be sources inside the headers?

Yes. In fact, there are a lot of different things that could be inside a "header" (i.e. shared between sources).

  • Forward declarations
  • declarations/definition of functions/structs/classes/templates
  • implementation of inline and templated code

It becomes complicated, and in some cases (circular dependencies between symbols), impossible to keep it in one header.

Headers can be broken down into three parts

This means that, in an extreme case, you could have:

  • a forward declaration header
  • a declaration/definition header
  • an implementation header
  • an implementation source

Let's imagine we have a templated MyObject. We could have:

// - - - - MyObject_forward.hpp - - - - 
// This header is included by the code which need to know MyObject
// does exist, but nothing more.
template<typename T>
class MyObject ;

.

// - - - - MyObject_declaration.hpp - - - - 
// This header is included by the code which need to know how
// MyObject is defined, but nothing more.
#include <MyObject_forward.hpp>

template<typename T>
class MyObject
{
   public :
      MyObject() ;
   // Etc.
} ;

void doSomething() ;

.

// - - - - MyObject_implementation.hpp - - - - 
// This header is included by the code which need to see
// the implementation of the methods/functions of MyObject,
// but nothing more.
#include <MyObject_declaration.hpp>

template<typename T>
MyObject<T>::MyObject()
{
   doSomething() ;
}

// etc.

.

// - - - - MyObject_source.cpp - - - - 
// This source will have implementation that does not need to
// be shared, which, for templated code, usually means nothing...
#include <MyObject_implementation.hpp>

void doSomething()
{
   // etc.
} ;

// etc.

Wow!

In the "real life", it is usually less complicated. Most code will have only a simple header/source organisation, with some inlined code in the source.

But in other cases (templated objects knowing each others), I had to have for each object separate declaration and implementation headers, with an empty source including those headers just to help me see some compilation errors.

Another reason to break down headers into separate headers could be to speed up the compilation, limiting the quantity of symbols parsed to the strict necessary, and avoiding unecessary recompilation of a source who cares only for the forward declaration when an inline method implementation changed.

Conclusion

You should make your code organization both as simple as possible, and as modular as possible. Put as much as possible in the source file. Only expose in headers what needs to be shared.

But the day you'll have circular dependancies between templated objects, don't be surprised if your code organization becomes somewhat more "interesting" that the plain header/source organization...

^_^

pfabri
  • 885
  • 1
  • 9
  • 25
paercebal
  • 81,378
  • 38
  • 130
  • 159
22

in addition to all other answers, i will tell you what you DON'T place in a header file:
using declaration (the most common being using namespace std;) should not appear in a header file because they pollute the namespace of the source file in which it is included.

Adrien Plisson
  • 22,486
  • 6
  • 42
  • 73
  • +1 with a caveat that you can do using as long as it is in some detail namespace (or an anonymous namespace). But yes, never use `using` to bring stuff into global namespace in a header. – KitsuneYMG Dec 22 '09 at 12:40
  • +1 This one is much easier to answer. :) Also, header files should *not* contain *anonymous* namespaces. – sellibitze Dec 22 '09 at 16:35
  • It's fine for header files to contain anonymous namespaces, so long as you understand what that means, i.e. that each translation unit will have a different copy of the stuff you define namespace. Inline functions in anonymous namespaces are recommended in C++ for cases where you'd use `static inline` in C99, because of something to do with what happens when you combine internal linkage with templates. Anon namespaces let you "hide" functions, while preserving external linkage. – Steve Jessop Dec 22 '09 at 19:04
  • Steve, what you wrote didn't convince me. Please pick a concrete example where you think an anon namespace makes total sense in a header file. – sellibitze Dec 23 '09 at 19:23
11

What compiles into nothing (zero binary footprint) goes into header file.

Variables do not compile into nothing, but type declarations do (coz they only describe how variables behave).

functions do not, but inline functions do (or macros), because they produce code only where called.

templates are not code, they are only a recipe for creating code. so they also go in h files.

Pavel Radzivilovsky
  • 18,794
  • 5
  • 57
  • 67
  • 1
    "inline functions ... produce code only where called". That's not true. inline functions may or may not be inlined at call sites, but even if they are inlined, the real function body still exists just as it does for a non-inline function. The reason it's OK to have inline functions in headers is nothing to do with whether they generate code, it's because inline functions don't trigger the one definition rule, so unlike non-inline functions there are no problems with linking together two different translation units which have both included the header. – Steve Jessop Dec 22 '09 at 18:57
5

In general, you put declarations in the header file and definitions in the implementation (.cpp) file. The exception to this is templates, where the definition must also go in the header.

This question and ones similar to it has been asked frequently on SO - see Why have header files and .cpp files in C++? and C++ Header Files, Code Separation for example.

Community
  • 1
  • 1
3

Header (.h)

  • Macros and includes needed for the interfaces (as few as possible)
  • The declaration of the functions and classes
  • Documentation of the interface
  • Declaration of inline functions/methods, if any
  • extern to global variables (if any)

Body (.cpp)

  • Rest of macros and includes
  • Include the header of the module
  • Definition of functions and methods
  • Global variables (if any)

As a rule of thumb, you put the "shared" part of the module on the .h (the part that other modules needs to be able to see) and the "not shared" part on the .cpp

PD: Yes, I've included global variables. I've used them some times and it's important not to define them on the headers, or you'll get a lot of modules, each defining its own variable.

Shidouuu
  • 368
  • 4
  • 14
Khelben
  • 6,283
  • 6
  • 33
  • 46
  • As a rule of thumb, as few includes as possible should be in the .h file, and the .cpp file should include whatever headers it needs. That shortens compile times and doesn't pollute namespaces. – David Thornley Dec 23 '09 at 16:54
3

Mainly header file contain class skeleton or declaration (does not change frequently)

and cpp file contains class implementation (changes frequently).

Ashish
  • 8,441
  • 12
  • 55
  • 92
  • 7
    Please refrain from using non-standard terminology. What's "class skeleton", what's "class implementation"? Also, what you call declaration in context of classes probably includes class definitions. – sellibitze Dec 22 '09 at 16:30
2

Your class and function declarations plus the documentation, and the definitions for inline functions/methods (although some prefer to put them in separate .inl files).

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
2

the header file (.h) should be for declarations of classes, structs and its methods, prototypes, etc. The implementation of those objects are made in cpp.

in .h

    class Foo {
    int j;

    Foo();
    Foo(int)
    void DoSomething();
}
jose
  • 2,733
  • 4
  • 37
  • 51
2

I'd expect to see:

  • declarations
  • comments
  • definitions marked inline
  • templates

the really answer though is what not to put in:

  • definitons (can lead to things being multiply defined)
  • using declarations/directives (forces them on anyone including your header, can cause nameclashes)
jk.
  • 13,817
  • 5
  • 37
  • 50
  • 1
    You can certainly put *class definitions* into header files as well. A *class declaration* doesn't say anything about its members. – sellibitze Dec 22 '09 at 16:32
2

The header Defines something but doesn't tell anything about the implementation. ( Excluding Templates in this "metafore".

With that said, you need to divide "definitions" into sub-groups, there are, in this case, two types of definitions.

  • You define the "layout" of your strucutre, telling only as much as is needed by the surrounding usage groups.
  • The definitions of a variable, function and a class.

Now, I am of course talking about the first subgroup.

The header is there to define the layout of your structure in order to help the rest of the software use the implementation. You might want to see it as an "abstraction" of your implementation, which is vaughly said but, I think it suits quite well in this case.

As previous posters have said and shown you declare private and public usage areas and their headers, this also includes private and public variables. Now, I don't want to go into design of the code here but, you might want to consider what you put in your headers, since that is the Layer between the end user and the implementation.

Filip Ekberg
  • 36,033
  • 20
  • 126
  • 183
2
  • Header files - shouldn't change during development too often -> you should think, and write them at once (in ideal case)
  • Source files - changes during implementation
nothrow
  • 15,882
  • 9
  • 57
  • 104
  • This is one practice. For some smaller projects, it might be the way to go. But you might try deprecating functions and their prototypes (in header files), rather than changing their signature or removing them. At least until changing the major number. Like when 1.9.2 is bumped to 2.0.0 beta. – TamusJRoyce Dec 03 '18 at 01:15