55

I'm wondering if it's a good practice to store C++ regular functions, not methods(the ones in classes) inside header files.

Example:

#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED

int add(int a, int b)
{
   return a + b;
}

#endif

And Use it like this:

#include <iostream>
#include "Functions.h"

int main(int argc, char* args[])
{
    std::cout << add(5, 8) << std::endl;
    return 1;
}

Is this a good a good practice?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Nobody
  • 605
  • 1
  • 7
  • 9
  • 15
    No, you're inevitably going to violate the One Definition Rule. – chris Aug 12 '14 at 21:27
  • 1
    Think about what would happen if the header file was included in two or more source files. – Some programmer dude Aug 12 '14 at 21:28
  • 3
    @chris Why? Aren't the include guards precisely to prevent that? – Daniel Daranas Aug 12 '14 at 21:29
  • 14
    @DanielDaranas No, the include guards protect against including the same header file multiple times *in the same source file*. It doesn't protect against inclusion over multiple source files (how would that even work if compiling source files separately into object files?) Also read about [translation units](http://en.wikipedia.org/wiki/Translation_unit_%28programming%29) (And the OP: You should read the link too) – Some programmer dude Aug 12 '14 at 21:29
  • so is there any other way i can store my functions in another file, then include it in my program? – Nobody Aug 12 '14 at 21:29
  • You can create a class that has all your needed small functions and make them public and static so those that include the header have access to them. – Benjamin Trent Aug 12 '14 at 21:31
  • can you please show some code sample? – Nobody Aug 12 '14 at 21:32
  • 12
    You would have to mark the function `inline` to avoid breaking the *one definition rule*. – juanchopanza Aug 12 '14 at 21:34
  • But it's still a bad idea as it harms compile times. – Neil Kirk Aug 12 '14 at 21:48
  • @JoachimPileborg Thank you, I got it now. A very interesting difference. – Daniel Daranas Aug 12 '14 at 23:58
  • 1
    Remember that if changes are made to one or more functions in the header file, all files including that header file must be rebuilt. If the changes were made to functions in a source file, only that source file would need to be rebuilt. – Thomas Matthews Aug 13 '14 at 00:27

3 Answers3

83

If you want to use a function in multiple source files (or rather, translation units), then you place a function declaration (i.e. a function prototype) in the header file, and the definition in one source file.

Then when you build, you first compile the source files to object files, and then you link the object files into the final executable.


Example code:

  • Header file

      #ifndef FUNCTIONS_H_INCLUDED
      #define FUNCTIONS_H_INCLUDED
    
      int add(int a, int b);  // Function prototype, its declaration
    
      #endif
    
  • First source file

      #include "functions.h"
    
      // Function definition
      int add(int a, int b)
      {
          return a + b;
      }
    
  • Second source file

      #include <iostream>
      #include "functions.h"
    
      int main()
      {
          std::cout << "add(1, 2) = " << add(1, 2) << '\n';
      }
    

How you build it depends very much on your environment. If you are using an IDE (like Visual Studio, Eclipse, Xcode etc.) then you put all files into the project in the correct places.

If you are building from the command line in, for example, Linux or OSX, then you do:

$ g++ -c file1.cpp
$ g++ -c file2.cpp
$ g++ file1.o file2.o -o my_program

The flag -c tells the compiler to generate an object file, and name it the same as the source file but with a .o suffix. The last command links the two object files together to form the final executable, and names it my_program (that's what the -o option does, tells the name of the output file).

Matias Chara
  • 921
  • 6
  • 21
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Why do we need to put `#include "functions.h"` in the First source file ? – Roy Assis Oct 16 '22 at 13:43
  • 1
    @RoyAssis In this simple case it might not be needed. But think about when the function implementation needs some structures, macros or other things defined or declared in the header file? Would you rather include the header file where everything is already written, or copy-paste it yourself into the source file? And if you select copy-paste, think about what happens if you need to modify something in the header file, but forget to do the same edit in the source file? – Some programmer dude Oct 16 '22 at 16:36
  • Function `add` is a one-liner. When is it acceptable to put a function definition in a header file? I've heard somewhere that short member functions are OK to be defined in a header file, **IF** you do not need to `#include` anything extra apart from what's needed to include to declare that function. Does such rule make any sense? – mercury0114 Mar 06 '23 at 16:36
  • 1
    @mercury0114 If you define (implement) a function in a header file, it must be marked as `inline` or `static` or you will get multiple definition errors if you include the header file in multiple [translation units](https://en.wikipedia.org/wiki/Translation_unit_(programming)). There might also be other considerations, it all depends on use-case. – Some programmer dude Mar 06 '23 at 16:42
  • @Someprogrammerdude yes, so my question was about `inline` functions. – mercury0114 Mar 06 '23 at 16:46
  • How does the compiler solve this issues for classes that contain functions that are implemented entirely in the header? – TheGaldozer Apr 11 '23 at 19:47
  • 1
    @TheGaldozer If the functions are defined (implemented) *inline* inside the class itself, then the compiler marks them as `inline` automatically and they can be used like any other function. If you define the functions outside of the class you have to mark them as `inline` yourself. That prevents multiple definition errors. – Some programmer dude Apr 11 '23 at 23:54
37

No. After preprocessing, each source file will contain the header file. Then, at the linking stage you will end up with a multiple definition error because you will have multiple definitions of the same function.

Using inline or static will get rid of the linking error. Unless you want the function to be inline, it is best to declare the function in the header and define it in a single source file and link it.

If you declare the function as inline, then each of its function call in the source file will be replaced with the code inside the inlined function. So, there's no extra symbol defined.

If you declare the function as static, then the function symbol will not be exported from the translation unit. Therefore, no duplicate symbols.

Adding to what is said above, a function defined entirely inside a class/struct/union definition, whether it's a member function or a non-member friend function , is implicitly an inline function. So you do not need to explicitly write inline for the mentioned situations.

Koi.
  • 5
  • 2
Nikopol
  • 1,091
  • 1
  • 13
  • 24
  • `inline` will get rid of linking errors, but it won't replace each function call with the code inside the `inline` function - it won't inline it. – Tachi May 08 '23 at 17:07
26

No. If you import the same header from two files, you get redefinition of function.

However, it's usual if the function is inline. Every file needs it's definition to generate code, so people usually put the definition in header.

Using static also works because of fact that static functions are not exported from object file and in this way can't interfere with other functions with the same name during linkage.

It's also OK to define member functions inside the class in header as C++ standard considers them as inline.

Alexey Shmalko
  • 3,678
  • 1
  • 19
  • 35