应该在头文件和实现文件(C ++)中重复'#include'和'using'语句吗?

时间:2010-04-26 23:34:08

标签: c++ include header-files using-statement

我对C ++很新,但我的理解是#include语句基本上只是将#included文件的内容转储到该语句的位置。这意味着如果我的头文件中有一些'#include'和'using'语句,我的实现文件只能#include头文件,编译器不介意我不重复其他语句

虽然人们怎么样?

我主要担心的是,如果我不重复'#include','using',以及'typedef'(现在我想到它)语句,它会从文件中删除它的信息。使用,这可能会导致混淆。

我目前正在处理小型项目,但这并不会导致任何问题,但我可以想象,在有更多人工作的大型项目中,这可能会成为一个重大问题。

以下是一个例子:

UPDATE:我的'Unit'函数原型在它们的返回类型和参数中有字符串,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

5 个答案:

答案 0 :(得分:6)

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

应谨慎使用类型别名(通过typedef std::string string;using string = std::string;)。类型定义具有意义,因此您永远不应重新声明它。例如,这是一个错误:

typedef int   myint;
typedef float myint;

因为类型冲突。

using-declaration using std::string;using std::memcpy;)使unqualified name lookup可以访问符号。获取argument-dependent lookup正确时非常有用,除非您正在编写库,否则通常无关紧要。根据您是否引入类型或功能,建议会有所不同。考虑 using-declaration 的类型与类型别名相同:在同一名称下有多个定义没有意义。对于函数,你所做的只是扩展重载决策以包含更多的东西(尽管通常没有必要)。

// 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,您应该考虑是否确实需要首先将文件包含在标题中。也许forward declaration符合您的需求。

答案 1 :(得分:3)

  • 只在头/源中包含您真正需要的内容(如果前向声明可用,并且足够,则转发声明而不是包括在内)
  • 不要在标题中使用using语句(除非在函数范围内)...在标题中添加using会污染所有源的名称空间,包括报头中。
  • 您应确保每个文件(来源标题)包含所需的一切,仅此而已。

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

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

例如,假设您在标题和源代码中使用std::string,但是,作为“优化”,您只在标题中包含字符串...如果您稍后发现,则不要t还需要标题中的字符串,并希望将其删除(代码清理,以及所有...),您必须修改源代码以包含字符串。现在,让我们假设你有TEN来源,包括标题......

现在,当然,你可以有这个规则的例外(例如,预编译的标题,甚至标题是唯一的目的是做多个包含作为礼貌),但默认情况下,你应该有自给自足的标题和源文件(即包含任何内容的文件,不多也不少)。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

像Travis说的那样,你不应该在头文件中有using个语句,因为这意味着它们将包含在包含该头文件的所有翻译单元中,这可能会导致令人困惑的问题。

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

答案 4 :(得分:0)

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

每个typedef在代码库中只应存在一次。如果需要在多个cpp / h文件中使用它,那应该在头文件中。复制它们会让你感到很悲伤。

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