2

我的头文件如下所示:

// A.hpp --- A's interface

#ifndef MY_H
#define MY_H

#include<string>
#include<vector>

class A {
 public:
  A(const std::string& name);
  std::vector<double> foo() const;
 private:
  std::string m_name;
};

#endif

我的实现文件如下所示:

// A.cpp --- A's interface implementation
#include<A.hpp>

#include<implementation_detail.hpp>

A::A(const std::string& name)
 : m_name(name) { }

std::vector<double> A::foo() const {
 std::vector<double> r;
 r.push_back(1);
 return r;
}

我的立场是我没有#include stringvector在实现文件中没有,因为它们已经在接口中声明,并且#include在实现文件中添加它们充其量是多余的,更糟的是有害**。

当然,A的实现将在界面中不可见的#include所有实现细节。

我的问题:我是对的吗?这种做法会对我的代码产生负面影响吗?

** 这有点牵强,但是包含的数量(以及使用的包含保护)会影响非常大的项目的编译速度;这篇文章很有趣

4

4 回答 4

2

这是风格和个人喜好的问题。

对于头文件,我个人的偏好是让头文件独立存在,但只是勉强。通过“独立”,我的意思是我应该能够#include在一些随机源文件中使用该标头,并且该源文件仍将编译。

#include "some_random_header_file.h"
int main () {}

以上内容应始终编译。通过“勉强”,我的意思是标题应该没有免费的#include指令。如果某些#include不提供直接在头文件中使用的功能,我不会#include在头文件中使用其他头。

对于源文件,我个人的偏好是#include提供源文件中使用的功能的每个标头。如果源文件调用的代码std::string::append,该源文件最好#include <string>——即使其他一些头文件已经包含它。

于 2013-10-31T22:39:10.000 回答
1

你是对的。cpp 文件是编译单元。那就是使用标题的地方。这些标头包含的所有内容也有效地在 cpp 文件中。

值得注意的是:

  • 不要在标头的 cpp 文件中包含您需要的内容。
  • 在标题中明确说明您的类型。即 在标题中std::string不用作类型using std::string,甚至更糟。using namespace std;
  • 可以在 cpp 文件中方便地使用using语句。

您不想向包括您的标头在内的人员介绍不必要的类型。

于 2013-10-31T22:30:39.917 回答
0

这是风格问题,而不是正确性问题。

然而,包含绝对需要的东西被认为是一种很好的风格。因此,如果您的界面需要这些标头,那么您.h必须包含它们。

同时,让每个标题自给自足被认为是一种很好的风格——也就是说,为了使用它的设施,包含它而不包含其他任何东西就足够了。

因此,鉴于这两点,您#include在标题中包含这些指令是正确的。

于 2013-10-31T22:25:50.150 回答
0

如果你真的很关心#include性能,你有一些选择:

于 2013-10-31T22:36:56.743 回答