Is It a Good Practice to Define C++ Functions Inside Header Files

Is it a good practice to define C++ functions inside header files?

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).

Is it better to keep functions in header files or source files

Header files should not contain any code or data definitions.

In header files:

  1. Function prototypes
  2. Types declarations (typedefs, structs, unions etc)
  3. extern objects declarations
  4. Macro definitions

and as an exception


  1. static inline functions definitions.

All other code or object definitions should be in the .c source files.

Is it ok to keep simple C++ method definitions inside of a header file?

@ReinstateMonica left a really good, succinct answer which I wholeheartedly agree with -- however I wanted to expand a little on it.

There is nothing inherently "good" or "bad" about defining functions inline in a header. There can be some cases where it is better to not define in a header since it may cause code-bloat; but this is something that would be determined after examining the product.

What matters most is that your code is easy to read and understand, because this increases maintainability -- it doesn't matter whether someone else will be the maintainer, or if its yourself a year from now.

In my experience working in large projects in C++, it becomes common to rely on header files as the form of "living documentation" in order to see what functionalities are introduced in any given header at a glance. Having code be simple to digest at a glance makes a huge difference on how quickly new code can be written using this API.

Function definitions that are written inline in the class definition can upset that readability by interrupting the natural flow. For example, consider the following two code snippets which are equivalent:

class Snake
{
public:

auto get_name() -> std::string
{
return m_name;
}

auto eat(const Fruit& fruit) -> void
{
..
// some really long definition
..
}

auto set_name(std::string name)
{
m_name = std::move(name);
}
};

Contrast this to the more succinct, but still inline:

class Snake
{
public:

auto get_name() const -> std::string;

auto eat(const Fruit& fruit) -> void;

auto set_name(std::string) -> void;
};

inline auto Snake::get_name() const -> void
{
return m_name;
}

inline auto Snake::eat(const Fruit& fruit) -> void
{
..
// some really long definition
..
}

inline auto Snake::set_name(std::string) -> void
{
m_name = std::move(name);
}

By simply relocating the definitions to the bottom and explicitly marking these inline, we get a quick topological view of the Snake class and all related actors and observer functionalities on it without having to scan between function definitions.

This will not change code generation in the slightest, but it can help to improve readability of the class by making it self-documenting -- which can be very useful if you work in a team environment, or ever have someone else come in to maintain your project.

Writing function definition in header files in C++

If the function is small (the chance you would change it often is low), and if the function can be put into the header without including myriads of other headers (because your function depends on them), it is perfectly valid to do so. If you declare them extern inline, then the compiler is required to give it the same address for every compilation unit:

headera.h:

inline string method() {
return something;
}

Member functions are implicit inline provided they are defined inside their class. The same stuff is true for them true: If they can be put into the header without hassle, you can indeed do so.

Because the code of the function is put into the header and visible, the compiler is able to inline calls to them, that is, putting code of the function directly at the call site (not so much because you put inline before it, but more because the compiler decides that way, though. Putting inline only is a hint to the compiler regarding that). That can result in a performance improvement, because the compiler now sees where arguments match variables local to the function, and where argument doesn't alias each other - and last but not least, function frame allocation isn't needed anymore.

My understanding is when the compilation is done, compiler will expand the header file and place it where it is included. Is that correct?

Yes, that is correct. The function will be defined in every place where you include its header. The compiler will care about putting only one instance of it into the resulting program, by eliminating the others.

How do you define functions in header files?

You should only write your function's prototype in the header file, the body of your function should be written in a .c file.

Do this :

primary_header.h

/* primary_header.h */
#ifndef PRIMARY_HEADER_H
#define PRIMARY_HEADER_H

#include <stdio.h>

/* Forward declare the primary workhorse function */
void primary(void);

/* Also define a helper function */
void helper(void);

#endif /* PRIMARY_HEADER_H */

primary_impl.c

/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>

/* Define the primary workhorse function */
void primary()
{
/* do the main work */
printf("I'm the primary function, I'm doin' work.\n");

/* also get some help from the helper function */
helper();
}

void helper()
{
printf("I'm a helper function and I helped!\n");
}

Edit: change _PRIMARY_HEADER_H to PRIMARY_HEADER_H. As @Jonathan Leffler and @Pablo said, underscore names are reserved identifiers

Is it good practice to define a function on a code file, but not declare it on the header?

By not declaring the function in the header file, you are simply ommiting information about the function, not the visibility of the function.

Declare it static (and omit from the header file).

// barfoo.h
int bar(void);


//barfoo.c
#include "barfoo.h"
static int foo(void) { return 42; }
int bar(void) { return foo(); }


//main.c
#include "barfoo.h"
int main(void) {
bar();
}

In this example, if foo() wasn't defined with static it could still be called from main(). With static the linker will report an error if you try to use it.

Is it a good practice to place C++ definitions in header files?

Your coworker is wrong, the common way is and always has been to put code in .cpp files (or whatever extension you like) and declarations in headers.

There is occasionally some merit to putting code in the header, this can allow more clever inlining by the compiler. But at the same time, it can destroy your compile times since all code has to be processed every time it is included by the compiler.

Finally, it is often annoying to have circular object relationships (sometimes desired) when all the code is the headers.

Bottom line, you were right, he is wrong.

EDIT: I have been thinking about your question. There is one case where what he says is true. templates. Many newer "modern" libraries such as boost make heavy use of templates and often are "header only." However, this should only be done when dealing with templates as it is the only way to do it when dealing with them.

EDIT: Some people would like a little more clarification, here's some thoughts on the downsides to writing "header only" code:

If you search around, you will see quite a lot of people trying to find a way to reduce compile times when dealing with boost. For example: How to reduce compilation times with Boost Asio, which is seeing a 14s compile of a single 1K file with boost included. 14s may not seem to be "exploding", but it is certainly a lot longer than typical and can add up quite quickly when dealing with a large project. Header only libraries do affect compile times in a quite measurable way. We just tolerate it because boost is so useful.

Additionally, there are many things which cannot be done in headers only (even boost has libraries you need to link to for certain parts such as threads, filesystem, etc). A Primary example is that you cannot have simple global objects in header only libs (unless you resort to the abomination that is a singleton) as you will run into multiple definition errors. NOTE: C++17's inline variables will make this particular example doable in the future.

As a final point, when using boost as an example of header only code, a huge detail often gets missed.

Boost is library, not user level code. so it doesn't change that often. In user code, if you put everything in headers, every little change will cause you to have to recompile the entire project. That's a monumental waste of time (and is not the case for libraries that don't change from compile to compile). When you split things between header/source and better yet, use forward declarations to reduce includes, you can save hours of recompiling when added up across a day.

Should the header file containing function prototypes be included in file with definitions?

Yes you should because it makes sure that the function signature is the same in the declaration and the definition. If they don't match the program won't compile. It is also a good idea to include myfunc.h before any other include file in myfunc.c. That way you will know that the header file is self-contained.



Related Topics



Leave a reply



Submit