应该“#include”和“使用”声明在头文件和实现文件中重复(C++)?

发布于 2024-08-30 12:46:55 字数 1075 浏览 8 评论 0原文

我对 C++ 相当陌生,但我的理解是 #include 语句本质上只是将 #included 文件的内容转储到该语句的位置。这意味着如果我的头文件中有许多“#include”和“using”语句,我的实现文件可以只#include头文件,并且编译器不会介意我不重复其他语句。

那么人呢?

我主要担心的是,如果我不重复“#include”、“using”和“typedef”(现在我想到了)语句,它就会从使用它的文件中删除该信息,这可能会导致混乱。

我目前正在从事小型项目,它不会真正引起任何问题,但我可以想象,在有更多人参与的大型项目中,这可能会成为一个重大问题。

示例如下:

更新:“Unit”的函数原型在其返回类型和参数中包含 string、ostream 和 StringSet - 我没有在头文件中包含仅在实现文件中使用的任何内容。

//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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

痴梦一场 2024-09-06 12:46:55

using-directiveusing namespace std;)不应驻留在标头中,除非它包含在函数中。这是不好的做法。标头的每个用户不太可能都希望对给定名称空间中的所有内容进行不合格的查找;包含不相关的标头可能会导致意外的歧义和编译失败。就我个人而言,出于同样的原因,我避免在函数内部使用 using-directive,但这通常被认为危害较小。

应谨慎使用类型别名(通过typedef std::string string;using string = std::string;)。类型定义是有意义的,所以你不应该重新声明它。例如,这是一个错误:

typedef int   myint;
typedef float myint;

因为类型冲突。

using-declarationusing std::string;using std::memcpy;)使 非限定名称查找。当获得依赖参数的查找正确时,它非常有用,而这通常不会'除非你正在写一个库,否则没关系。根据您是否引入类型或函数,建议会有所不同。将使用声明与类型的方式想象为类型别名:同一个名称下有多个定义是没有意义的。对于函数,您真正要做的就是扩展重载解析以包含更多内容(尽管通常没有必要)。

// 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;

对于重复#include,您应该首先考虑是否确实需要在标头中包含该文件。也许转发声明适合您需要。

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.

甚是思念 2024-09-06 12:46:55
  • 仅在标头/源代码中包含您真正需要的内容(如果前向声明可用且足够,则前向声明而不是包含)
  • 不要使用 using标头中的语句(除非在函数作用域内)...在标头中添加 using 会污染包括标头在内的所有源的命名空间。
  • 您应该确保每个文件(源头)包含它需要的所有内容,仅此而已。

您不需要关心某些包含是否多余。标头保护和预编译器优化可以为您处理这个问题。

您应该能够单独操作每个文件。

例如,假设您在标头和源代码中使用 std::string,但是,作为“优化”,您只在标头中包含了该字符串...如果您后来发现不再需要标头中的字符串,并且想要删除它(代码清理,以及所有...),您将不得不修改源以包含该字符串。现在,让我们假设您有十个源,包括标头...

现在,当然,您可以对此规则有例外(例如,预编译标头,甚至标头的唯一目的是出于礼貌而进行多次包含),但是默认情况下,您应该拥有自给自足的头文件和源文件(即包含它们使用的任何内容的文件,不多也不少)。

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

对风讲故事 2024-09-06 12:46:55

将头文件保持在最低限度。这意味着尽可能少的包含。 .cpp 文件通常包含相应的标头以及实现所需的任何其他标头。

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.

舞袖。长 2024-09-06 12:46:55

就像 Travis 所说,头文件中不应该有 using 语句,因为这意味着它们将包含在包含该头文件的所有翻译单元中,这可能会导致混乱的问题。

如果我只需要 cpp 文件中头文件的功能,我只将其包含在该 cpp 文件中。对于大型项目来说这是一个很好的做法,因为这意味着编译器的工作量更少。另外,只要有可能,我都会在标头中使用前向声明而不是包含(并且再次将标头包含在 cpp 文件中)。

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

千仐 2024-09-06 12:46:55

在头文件中使用 using 语句被认为是一种不好的形式,除非您有意将符号复制到不同的命名空间中。在cpp文件中使用就可以了。

每个 typedef 在代码库中只能存在一次。如果需要在多个 cpp/h 文件中使用,则应该将其放在头文件中。重复它们会给你带来很多痛苦。

头文件应该包含它需要的所有 #include 语句,而不包含其他语句。如果仅提到指向类的指针,则使用前向声明而不是包含标头。仅在 cpp 文件内需要的任何其他包含内容都应该放在那里。重复标头中的包含内容是可以的,但不是必需的。这只是一种风格选择。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文