Should '#include' and 'using' statements be repeated in both header and implementation files (C++)?

岁酱吖の 提交于 2019-12-06 02:13:47

问题


I'm fairly new to C++, but my understanding is that a #include statement will essentially just dump the contents of the #included file into the location of that statement. This means that if I have a number of '#include' and 'using' statements in my header file, my implementation file can just #include the header file, and the compiler won't mind if I don't repeat the other statements.

What about people though?

My main concern is that if I don't repeat the '#include', 'using', and also 'typedef' (now that I think of it) statements, it takes that information away from the file in which it's used, which could lead to confusion.

I am just working on small projects at the moment where it won't really cause any issues, but I can imagine that in larger projects with more people working on them it could become a significant issue.

An example follows:

UPDATE: my function prototypes for 'Unit' have string, ostream and StringSet among their return types and parameters - I am not including anything in my header file that is used only in the implementation file.

//Unit.h

#include <string>
#include <ostream>
#include "StringSet.h"

using std::string;
using std::ostream;

class Unit {

public:
    //public members with string, ostream and StringSet
    //in their return values/parameter lists
private:
    //private members
    //unrelated side-question: should private members
    //even be included in the header file?
} ;


//Unit.cpp

#include "Unit.h"

//The following are all redundant from a compiler perspective:
#include <string>
#include <ostream>
#include "StringSet.h"

using std::string;
using std::ostream;

//implementation goes here

回答1:


A using-directive (using namespace std;) should not reside in a header unless it is contained within a function. It is bad practice. It is unlikely that every user of your header wants unqualified lookup for everything in a given namespace; the inclusion of unrelated headers can lead to unexpected ambiguity and compilation failures. Personally, I avoid the using-directive inside of functions for the same reasoning, but this is generally considered less harmful.

A type alias (either through typedef std::string string; or using string = std::string;) should be used carefully. Type definitions have meaning, so you should never redeclare it. For example, this is an error:

typedef int   myint;
typedef float myint;

because of conflicting types.

A using-declaration (using std::string; or using std::memcpy;) makes a symbol accessible for unqualified name lookup. It is extremely useful when getting for argument-dependent lookup correct, which usually doesn't matter unless you're writing a library. The advice is different depending on if you are bringing in a type or a function. Think of using-declarations with types in the same manner as a type alias: It does not make sense to have multiple definitions under the same name. With functions, all you are really doing is extending overload resolution to include a few more things (although it is usually not necessary).

// Finding multiple operator<< functions makes sense
using std::operator<<;
using mylib::operator<<;

// Finding multiple string classes does not make sense
using std::string;
using mylib::string;

For repeating #include, you should consider if you actually need to include the file in the header in the first place. Perhaps a forward declaration fits your needs.




回答2:


  • Only include in a header/source what you really need (if forward declarations are available, and enough, then forward declare instead of including)
  • Don't use using statement in headers (unless inside function scopes)... Adding using in the header will pollute the namespaces of all the sources including the header.
  • You should make sure each file (header of source) includes everything it needs, and nothing more.

You don't need to care if some includes are redundant. Header guards and precompiler optimizations are there to handle that for you.

You should be able to manipulate each file in isolation.

For example, let's say you use the std::string in the header and in the source, but, as an "optimization", you only included the string in the header... If you discover later you don't need anymore the string in the header, and want to remove it (code cleaning, and all...), you will have to modify the source to include the string. Now, let's imagine you have TEN sources including the header...

Now, of course, you can have exceptions to this rule (for example, precompiled headers, or even headers woe sole aim is to do multiple includes as a courtesy), but by default, you should have self-sufficient header and source files (i.e. files that include anything they use, no more no less).




回答3:


Keep the header files to a minimum. This means as little include's as feasible. the .cpp file will usually include the corresponding header as well as any other headers necessary for implementation.




回答4:


Like Travis said, you shouldn't have using statements in a header file because that means they will be included in all the translation units that include that header file, which can cause confusing issues.

If I only require the functionality from a header file in a cpp file, I only include it in that cpp file. It's good practice for larger projects because it means less work for the compiler. Also, wherever possible, I use forward declarations in the headers instead of includes (and again, include the headers in the cpp file).




回答5:


It's considered bad form to have a using statement in a header file at all, unless you are intentionally duplicating a symbol into a different namespace. It's ok to use in a cpp file.

Each typedef should exist only once in your codebase. That should be in a header file if it needs to be used in multiple cpp/h files. Duplicating them will cause you much grief.

A header file should have all the #include statements that it needs, and no others. If only pointers to a class are mentioned then use a forward declaration rather than including the header. Any other includes that are required only inside the cpp file should go there. Repeating the includes from the header is ok, but not required. It's just a style choice.



来源:https://stackoverflow.com/questions/2717700/should-include-and-using-statements-be-repeated-in-both-header-and-implemen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!