C++包含头文件问题

8

我是c/c++的新手,对以下问题感到困惑:

  1. 我是否应该将类声明放在自己的头文件中,将实际实现放在另一个文件中?
  2. 我应该在example.h文件还是example.cpp文件中放置像iostream这样的头文件?
  3. 如果所有类都需要使用iostream,我将一个类的头文件包含到另一个类的头文件中,这是否意味着我重复包含了iostream?
  4. 如果我使用了很多STL类,使用std::的好习惯是什么?

1
#4足够独特,值得单独提出问题。 - Cameron
这些是不错的问题,但将它们合并成一个问题“范围过大”。 - Fred Nurk
6个回答

8

1. 我是否应该将类声明放在自己的头文件中,而将实际实现放在另一个文件中?

如果您正在操作模板,则可以在同一头文件中分别编写类的定义和成员定义。此外,如果要使成员函数内联,可以在类定义本身中定义它们。在任何其他情况下,最好将类的定义(.hpp文件)和类成员的定义(.cpp文件)分开。

2. 是否应将头文件放在example.h文件中还是example.cpp文件中?

这取决于您是否仅需要在example.h文件或.cpp文件中使用这些头文件。

3. 如果所有类都需要使用,我将一个类的头文件包含到另一个类的头文件中,这意味着我已经包含了两次吗?

如果您没有使用以下宏来包装类定义,则会发生这种情况:

#ifndef FOO_HPP
#define FOO_HPP
class { 
...
};
#endif

如果我使用很多STL类,那么使用std::的好习惯是什么?
我认为最好每次都使用std::而不是using namespace std。这样,您将仅使用所需的命名空间,并且您的代码将更易读,因为您将避免命名空间冲突(想象一下具有相同名称并属于两个不同命名空间的两种方法)。
但更重要的是,问题4在哪里?

1
删除 FOO_HPP 前面的双下划线,我会点赞的。 ;) - Maxpm

2
  1. 通常是这样的。它有助于组织。但在小型项目中可能不是那么重要。

  2. 我在这里理解问题有些困难。如果你想知道在哪里放置#include指令,实现文件应该包含头文件。

  3. 是的,但使用include guards可以防止多次包含。


2
  1. 通常情况下你应该这样做,但是对于相对较小的项目,你可以尽可能地避免使用实现文件。
  2. 如果你的头文件只使用了来自 <iostream> 的不完全类型,你可以避免包含它,但你需要为这些类型进行前向声明(参见 何时使用前向声明?)。然而,为了简单起见,如果类型使用了模板,则我通常会包含相应的头文件。
  3. 不。包含保护可以确保同一个翻译单元中只包含一次头文件。
  4. 一个常见的好习惯是不要在头文件中使用 using namespace std。同时要注意命名空间冲突。

1
针对“重复包含”的问题,这里有一个常见的头文件模式:
// _BLAHCLASS_H_ should be different for each header, otherwise things will Go Bad.
#ifndef _BLAHCLASS_H_
#define _BLAHCLASS_H_

... rest of header ...

#endif

4
以双下划线开始的名称是为编译器实现保留的;你应该为你的包含保护符使用不同的模式(例如 BLAHCLASS_H_INCLUDED)。 - Matteo Italia
1
同意一般观点,但是人们为什么要使用双下划线呢(我到处都看到这个)。这些名称不是保留给实现的吗?(它们看起来很丑) - Benjamin Bannier

1
通常情况下,您会将类声明(包括成员声明)放入头文件中,并将成员函数(方法)的定义放入源文件中。头文件通常具有像*.h*.hpp这样的名称。至于第3点,您应该在头文件中放置包含保护,以便它们可以在同一源文件中安全地被多次包含;然后您可以在需要它们的任何地方包含它们。我不理解第5点:您是否在询问何时使用std::命名空间限定?

1
  1. 通常情况下,只要它们不是模板,就可以放在任何地方。模板(无论好坏)必须放在头文件中。
  2. 我喜欢让每个头文件都是“独立的”,所以如果需要其他头文件才能使其正常工作,它会包含该头文件本身(例如,如果我有一个使用 std::string 的类,那么该类的头文件将会 #include <string>
  3. 不会。除了一些特殊情况外,标准头文件必须编写成可以多次包含而不会改变任何内容(主要的例外是 assert.h/cassert,这时可能需要多次包含)。
  4. 我不确定你具体想问什么。如果你问的是像 using namespace std; 这样的 using 指令,那么它通常被人们所不喜欢(当然也不是普遍如此)。像 using std::vector; 这样的 using 声明通常被认为是较少问题的。

有一些方法可以将模板的实现与声明分离,但这可能超出了本问题的范围。 - Maxpm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接