Jose Luis
Jose Luis

Reputation: 59

Which is the correct way to use a header file in C++?

I have some questions reggarding this subject, but first let me give you some code:

example.hpp

#ifndef EXAMPLE_H_
#define EXAMPLE_H_

using namespace std;

void say_something(string something);

#endif

example.cpp

#include <string>
#include <iostream>
#include "example.hpp"

void say_something(string something)
{
    cout << something << '\n';
}

main.cpp

#include <iostream>
#include <string>
#include "example.hpp"

using namespace std;

int main()
{
    string hello = "Hello world!";
    say_something(hello);

    return 0;
}

Now, my questions are:

Upvotes: 2

Views: 436

Answers (3)

user2486888
user2486888

Reputation:

Should I put my all the header files that example.cpp is gonna need in the header example.hpp or should I keep them in the example.cpp like the example above?

Keep the header file minimal.

The header file provides a function declaration. The function declaration depends on things in <string> but not things in <iostream>. So the header file should include <string> without <iostream>.

If the header file includes unneccessary things, the user of the header file will include those unneccessary things too.

How the C++ will work in this situation: I've included 'string' and 'iostream' in both main.cpp and example.cpp... Is the C++ compiler gonna link (or whatever term you'll find more qualified) the program two times with the string and iostream headers? should I put the string and iostream headers only in the example.cpp

C++ sources does not link with headers. Whenever you write #include <string>, the preprocessor (conceptually) copy the entire header file named "string" and paste at the line of #include <string>. Preprocessing occurs before compilation and linking.

And finally, should I put the namespaces that I'm gonna use for my example header in the header itself (example.hpp) or in the implementation (example.cpp)?

Never write using namespace std; in the global scope of the header file. Due to the copy-and-paste nature of #include, the using-directive will infect other files that include the header. What if there is a file that wants to use say_something but does not want to using namespace std?

Upvotes: 3

Jts
Jts

Reputation: 3527

Should I put my all the header files that example.cpp is gonna need in the header example.hpp or should I keep them in the example.cpp like the example above?

No, you should not. A header file should only include the header file it requires.

How the C++ will work in this situation: I've included 'string' and 'iostream' in both main.cpp and example.cpp... Is the C++ compiler gonna link (or whatever term you'll find more qualified) the program two times with the string and iostream headers? should I put the string and iostream headers only in the example.cpp

The compiler will not link string or iostream twice, due to the include guards. It will just open the string header for example, and return as soon as the include guard tells the compiler it has already been included.

And finally, should I put the namespaces that I'm gonna use for my example header in the header itself (example.hpp) or in the implementation (example.cpp)?

This is the same as with include problem. If you place a "using namespace std;" in your header file, every other file that includes it will be forced to use the whole namespace. That's not a good thing, by the way.

Therefore, it is not evil to use namespace std in your implementation (after you've included all your headers).

In your header file, it's also fine to use "using namespace std" or just "using std::string" inside a function body, they will be restricted to the scope of the function body only.

  void somef(std::string str_arg)
  {
     using std::string;
     string str;

     // This is not evil either.    
     using namespace std;
     string str;
  }
  void somef2() {
     //string str; //error
  }

If somef is a method of a class, a common way is to use a typedef, for example:

class MyClass
{
    typedef std::string string_type;
    //using string_type = std::string; //C++11

    string_type data_member;

    void somef(string_type str)
    {
        string_type local_str;
    }

    void somef2() {
        string_type local_str; // works
    }
};
#include <string>
#include <iostream>
#include "example.hpp"

I would say this is also a bad order to use your header files. Assume example.hpp uses std::string. This will not throw a compile error because you have included <string> before example.hpp.

What happens if you use example.hpp in another file without including <string> before it then? You will get a compile error, because your header uses std::string and you have not included std::string.

Upvotes: 1

Galik
Galik

Reputation: 48655

  • Should I put my all the header files that example.cpp is gonna need in the header example.hpp or should I keep them in the example.cpp like the example above?

Include the header files in every file that needs them. Don't worry about duplication.

  • How the C++ will work in this situation: I've included 'string' and 'iostream' in both main.cpp and example.cpp... Is the C++ compiler gonna link (or whatever term you'll find more qualified) the program two times with the string and iostream headers? should I put the string and iostream headers only in the example.cpp

The header file itself makes sure its contents are only included once in any translation unit. This is achieved by the #ifdef EXAMPLE_H_ test.

  • And finally, should I put the namespaces that I'm gonna use for my example header in the header itself (example.hpp) or in the implementation (example.cpp)?

NEVER put using namespace ... in the global scope of a header file ever.

If you must use using namespace ... only use it inside your own namespace or function. Even then it is not advisable to use it for large namespaces like std that contains thousands of very common symbols that everybody uses all the time.

Also you should ideally only use using namespace ... in source .cpp files. However (as mentioned before) for small namespaces that should logically exist within your own namespace, sometime it is appropriate to include it in the non-global part of a header.

Upvotes: 0

Related Questions