11

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

人呢?

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

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

一个例子如下:

更新:我的“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
4

5 回答 5

9

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;or using std::memcpy;) 使符号可用于非限定名称查找在获取正确的参数相关查找时非常有用,除非您正在编写库,否则这通常无关紧要。根据您是引入类型还是函数,建议会有所不同。以与类型别名相同的方式考虑使用类型的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,您应该首先考虑是否真的需要将文件包含在标题中。也许前向声明适合您的需求。

于 2010-04-26T23:36:23.877 回答
5
  • 仅在标题/源中包含您真正需要的内容(如果前向声明可用且足够,则前向声明而不是包含)
  • 不要using在标头中使用语句(除非在函数范围内)...using在标头中添加会污染包括标头在内的所有源的名称空间。
  • 您应该确保每个文件(源文件头)都包含它需要的所有内容,仅此而已。

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

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

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

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

于 2010-08-06T22:05:00.977 回答
0

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

于 2010-04-26T23:41:30.087 回答
0

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

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

于 2010-04-26T23:43:23.587 回答
0

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

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

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

于 2010-04-26T23:46:42.100 回答