将其他 header 包含到包含 class 定义的 header 中
Inclusion of other headers into the header containing class definition
为什么我们需要将 headers(如 string
、iostream
)包含到包含 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
。
为什么我们需要将 headers(如 string
、iostream
)包含到包含 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
.
否则这个 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
。