将其他 header 包含到包含 class 定义的 header 中

Inclusion of other headers into the header containing class definition

为什么我们需要将 headers(如 stringiostream)包含到包含 class 定义的 header 中(class 需要 I/O 或字符串按比例分配)- 因为 header 已经包含在 cpp 翻译单元中,其中包含此 class header。

好像内容加倍了。 header material 不是首先粘贴到包含它的 cpp 文件中吗?

示例:

 //HEADER
 #ifndef SAMPLE_H
 #define SAMPLE_H

 class sample
 {
      public:
      sample();
 }

 sample::sample()
 {
     cout<<"Constructor!!!\n";     //error
 }

 #endif


//CPP
#include<iostream>
#include"m.h"

using namespace std;

int main()
{
    m obj();
    return 0;
}

抛出的错误是:

error: ‘cout’ was not declared in this scope

即使我在 cpp 文件中使用了 using namespace std。因此,要么我必须在 class 定义文件中包含 iostream,要么在使用 cout 之前使用 std - 但为什么呢?由于 iostream 和命名空间已经包含在主翻译单元中。

初学者请注意 class 定义中有错别字。您忘记在 class 定义

之后放置分号
class sample
{
      public:
      sample();
};
^^^ 

在某些上下文中使用的名称在使用前应已声明。

因此,如果 class 定义引用标准 class std::string,则应包括 header <string>

考虑到 header 可以被其他用户或编译单位使用,他们不知道在使用 [=36 之前需要包含 header <string> =] 与 class 定义。

在您的 header 示例中,您必须包含 header <iostream> 并使用限定名称 std::cout 或对 [= 使用 using 声明14=] 或命名空间 std.

的 using 指令

否则这个 header 可能是错误的来源,因为 header 的用户可能会忘记在他们的程序中包含 header <iostream>,然后再包含您的 header.

不必 包含其他 header;你可以有一个文件结构,只在源文件中放置必要的 #include 指令。但这真的很烦人,真的很快。

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H
struct S { std::string data; };
#endif MYHEADER_H

// test.cpp
#include <string>
#include "myheader.h"
S s; // ok

但是如果你遗漏了 #include 指令,你会得到一个错误:

// test.cpp
#include "myheader.h" // error: std::string undefined

通常的约定是编写可以自己编译的headers:

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H
#include <string>
struct S { std::string data; };
#endif MYHEADER_H

有了这个 header,test.cpp 的两个版本都可以编译。

这不会使内容加倍。 Headers 这样您就可以 #include 多次使用它们,而无需复制它们的内容。这就是 #ifndef 东西的用途。如果 header 已经被包含,预处理器将看到保护变量的定义(在这种情况下为 MYHEADER_H )并在第二次和后续时间跳过文件的内容。所以你可以这样写:

// test1.cpp
#include "myheader.h"
#include "myheader.h"

并且只获取一次myheader.h的内容。事实上,如果你遗漏了 include guards,如果你试图在同一个 cpp 文件中多次包含相同的 header,你会得到一个错误。

您可能会忽略的是 m.h 不仅包含在 test.cpp 中,而且可能还包含在许多其他需要 class sample 的文件中。如果您不在 m.h 中包含 <iostream>,您会强制所有其他文件包含 <iostream> before m.h.

对于更大的项目,您的策略可能会很难获得正确的 header 订单。 A.h 到 D.h 应按什么顺序包含在 E.cpp 中? E.cpp 的作者怎么会知道?

此规则有一个可行的例外。实际上,您可以有一个总是首先包含的 project-wide meta-header,然后包含一些常见的 header,例如 <string><vector>。如果您使用此策略,则这些 header 不需要包含在您自己的 .h 文件中。这种方法在 Visual C++ 中尤其常见,其中这样的 header 通常被命名为 stdafx.h