using namespace std;在头文件中

时间:2013-01-29 04:45:36

标签: c++ class namespaces header-files

所以,我在规范文件中有以下内容

#include <string>
#include <fstream>
using namespace std:

class MyStuff
{
    private:

    string name;
    fstream file;
    // other stuff

    public:
    void setName(string);
}

我也有实施文件

#include "MyStuff.h"
using namespace std;

void MyStuff::setName(string name);
{
     name = name
}

在程序文件中我有......

#include <iostream>
#include <string>
using namespace std;

void main()
{
     string name;
     MyStuff Stuff;

     cout << "Enter Your Name: ";
     getline(cin, name);

     Stuff.setName(name);
}

我正在收集应用“using namespace std;”在头文件中是禁止的,完全符合条件是“更好”的做法;例如std::cout << stuff << endl;

我的理解是,为了使用字符串,它必须具有std命名空间。这是真的吗?

如果是这样,在头文件中,更加“纯净/干净”来做...

#include <string>

class MyStuff
{
     std::string name;
}

而且,据我所知,目前使用命名空间std;在所有三个文件,规范,实现和程序中,基本上将三个命名空间层叠在一起,因此如果我在每个文件中单独声明string name;,编译器将不知道哪个归于什么。这是真的吗?

我一般都明白,明确是一个“好”的事情,但我对如何的特殊性有点不清楚,而且我最感兴趣的是更深层次的“为什么”这一点。

所以我的直接问题是,在我提供的示例中,描述编译器和行业“标准”功能的“最清晰”方法是什么?而且,您能否指引我更清楚地描述名称空间的推理和实际实现的资源。

3 个答案:

答案 0 :(得分:11)

假设我自己宣布了一个班级string。因为我是一个懒惰的流浪汉,我在全局命名空间中这样做。

// Solar's stuff
class string
{
    public:
        string();
        // ...
};

稍后,我意识到重新使用一些你的代码会使我的项目受益。感谢您将其设为开源,我可以这样做:

#include <solarstuff.hpp>
#include <phoenixstuff.hpp>

string foo;

但突然之间编译器不再喜欢我了。因为有::string(我的类)和另一个 ::string(标准版,包含在您的标题中,并带有using namespace std;进入全局命名空间),所以各种各样的痛苦。

更糟糕的是,这个问题会通过包含 my 标题的每个文件得到提升(其中包含您的标题,其中......您明白了。)

是的我知道,在这个例子中,我也应该责备我不在我自己的命名空间中保护自己的类,但那是我特意提出的那个。

命名空间可以避免标识符的冲突。您的标头不仅会将MyStuff引入全局命名空间,还会将 stringfstream中的每个标识符引入。我们中的任何一个人实际上都不需要他们中的大多数,所以为什么要将它们拖入全球,污染环境呢?

添加:从维护编码器/调试器的角度来看,foo::MyStuffMyStuff方便十倍,在其他地方命名空间(可能甚至不一样)源文件),因为您可以在代码中的所需位置获取命名空间信息。

答案 1 :(得分:8)

using namespace std;的多个实例不会导致任何歧义。问题是该语句将std的所有名称/类型/函数导入到您的命名空间中,现在如果您想要命名一个类string,您将遇到麻烦。使用删除,擦除等功能更有可能发生这种情况。

在标头中使用它会更糟糕,因为它会传播到该标头的所有.cpp,而不会包含它的人的意识。在.cpp中使用它至少需要有意识的选择。

更完整的解释可以在Why is "using namespace std" considered bad practice?

获得

可能由此产生的问题示例可以在How to use an iterator?中找到,其中OP定义了函数distance,并且一直得到错误的答案。 Confusion about pointers and references in C++

的另一个例子

答案 2 :(得分:2)

命名空间使用是为了您的方便,而不是您对其他人造成的:永远不要在#include指令之前编写using声明或using指令。

推论:在头文件中,不要使用指令或使用声明来编写命名空间级别;相反,显式命名空间限定所有名称。 (第二个规则从第一个开始,因为标题永远不会知道其他标题#includes可能会出现在它们之后。)

  

我一般都明白,明确是一件“好事”,我是   但有点不清楚如何的特殊性,而且我是最多的   对更深层次的“为什么”感兴趣。

下面的代码段反映了为什么在头文件中使用using namespace是错误的:

// snippet 1
namespace A {
 int f(double);
}

// snippet 2
namespace B {  
    using A::f;
    void g();
}

// snippet 3
namespace A {
    int f(int);
}

// snippet 4
void B::g() {
    f(1);   // which overload is called?
}

所以在你的例子中,只需要这个更好:

#include <string>

class MyStuff
{
    std::string name;
};

推荐书:C++ Coding Standards: 101 Rules, Guidelines, and Best Practices

并链接:Google C++ coding guide