在头文件中包含(STL)头文件

3
可能重复:
在实现中重新包含头文件 我想知道的是,在头文件中不使用using namespace xxx以避免污染全局命名空间,这是常见做法。 那么对于#include呢?
如果我有foo.hfoo.cpp。:
//Foo.h
#ifndef FOO_H_
#define FOO_H_

#include <string>

class Foo
{
  public:
    Foo(std::string * a, std::string * b);
    virtual ~Foo();
};

#endif /* FOO_H_ */

//Foo.cpp
#include <string>
#include <Foo.h>
Foo::Foo(std::string * a, std::string * b)
{
  // TODO Auto-generated constructor stub

}

Foo::~Foo()
{
  // TODO Auto-generated destructor stub
}

我真的需要在两个文件中都使用#include <string>吗?只在.h或.cpp文件中包含它是否就足够了?(我知道两者都可以工作,但哪种更可取?)
编辑,关于我的问题还有一些背景信息。 如果我在头文件中使用某些类(作为变量或方法参数),我会在头文件中进行前向声明,并仅在源文件中包含头文件本身。但这对于大多数STL库来说是行不通的,因为你无法前向声明类模板?

5
你只需要把它放在头文件中,但最好在每个需要使用它的文件中都包含所需的内容。 - chris
5
尽可能使用前置声明,必要时再使用 #include。这样做可以极大地减少编译时间。 - Chad
2
请将它们包含进来。唯一的替代方案是前向声明,而您肯定不想前向声明 namespace std { template <typename, typename, typename> class basic_string; typedef basic_string<char, std::char_traits<char>, std::allocator<char> > string; }。(我甚至不确定这是否正确) - Alexandre C.
1
@AlexandreC.:我非常确定这样的前向声明在技术上是未定义行为。C++03 §17.4.3.1/1说:“除非另有规定,否则向命名空间std或命名空间中添加声明或定义都是未定义的。” - Adam Rosenfield
1个回答

3
因为你无法前向声明类模板吗?
类模板可以像非模板类一样进行前向声明。
// forward declaration
template <typename T>
class C;

然而,正如@AlexandreC在评论中所述,对于std::string来说,这将是相当复杂的,因为std::string是从template <typename,typename,typename> basic_string;中typedef过来的。

如果允许的话,这将会很复杂。但事实上并不被允许,参见:

根据C++11标准,17.6.4.2.1:

如果未另行指定,则C ++程序的行为是未定义的,如果它向命名空间std或命名空间中的命名空间添加声明或定义std。

因此,除了在头文件中包含<string>以供std::string使用外,没有其他选择。

对于你的主要问题,我会在源文件和头文件中都包含它,除非我非常确定它将始终包含在头文件中且不会被删除...


我不确定从std命名空间中前向声明任何内容是否被允许。 - Alexandre C.
@AlexandreC。我时不时地会提前声明一些来自std命名空间的东西 - 从未考虑过是否允许。好吧,也许现在是开始思考这个问题的好时机... - PiotrNycz
3
我相信在命名空间std中前置声明任何内容在技术上都是未定义的行为。C++03 §17.4.3.1/1说:“除非另有规定,否则向命名空间std或命名空间中的命名空间添加声明或定义在C++程序中是未定义的。” - Adam Rosenfield
@AdamRosenfield 你是正确的。 - PiotrNycz
我不确定这个引用是否独立存在。从技术上讲,您并没有向命名空间中“添加”任何内容,您只是告诉编译器它在那里,并且在正确包含后将会存在。另一方面,在模板的情况下,标准允许实现添加任意数量的模板参数,只要有默认值,这使得以可移植的方式前向声明模板变得不可能。 - David Rodríguez - dribeas
显示剩余3条评论

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