Search code examples
c++headerheader-filesduplicate-symbolnumerical-recipes

Including a header in multiple headers in my C++ code


I am trying to include a header file from the book Numerical Recipes in my code. The header files I have to include are the nr3.hpp and the interp_1d.hpp. The interp_1d needs the definitions of nr3 in order to work.

I will write some of the code that appears on interp_1d.hpp so that you get an idea of what I am dealing with with the interp_1d code:

struct Base_interp{
...
};
Int Base_interp::locate(const Doub x){
...
}
...
Doub BaryRat_interp::interp(Doub x){
...
}

There are no header guards in this header file. As a result when I try to input it in multiple other header files I get the error "66 duplicate symbols for architecture x86_64".

The structure of my code is the following:

myPulse.hpp:
#include "nr3.hpp"
#include "interp_1d.hpp"

calc1.hpp:
#include "myPulse.hpp"

calc2.hpp:
#include "myPulse.hpp"

main.cpp:
#include "myPulse.hpp"
#include "calc1.hpp"
#include "calc2.hpp"
#include "nr3.hpp"
#include "interp_1d.hpp"

I don't know how to overcome this issue. I want to be able to use the interp_1d.hpp functions in more than one part of the code. I tried including header guards, but this didn't work:

#ifndef Interp_1d
#define Interp_1d

#endif

Does anyone know how I use the interp_1d header in multiple other headers without this error occurring?


Solution

  • When working with a single file (or for brevity for books), some code can be simplified, but making multi-file case wrong.

    In your case, header guards are missing, and inline are missing (or a cpp file to put definition).

    So you cannot use them as-is.

    You have either:

    • split code for header/cpp file:

      // interp_1d.hpp
      #pragma once // or include guards
      struct Base_interp{
      //...
      };
      
      //interp_1d.cpp
      #include "interp_1d.hpp"
      Int Base_interp::locate(const Doub x){
      //...
      }
      
      Doub BaryRat_interp::interp(Doub x){
      //...
      }
      
    • or put extra inline/static (not always enough/possible though (globals for example)) and header guard.

      // interp_1d.hpp
      #pragma once // or include guards
      struct Base_interp{
      //...
      };
      
      inline Int Base_interp::locate(const Doub x){
      //...
      }
      
      inline Doub BaryRat_interp::interp(Doub x){
      //...
      }