using namespace std; in a header file

我怕爱的太早我们不能终老 提交于 2019-11-26 05:37:51

问题


So, I have the following in a specification file

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

class MyStuff
{
    private:

    string name;
    fstream file;
    // other stuff

    public:
    void setName(string);
}

I also have in the implementation file

#include \"MyStuff.h\"
using namespace std;

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

and in the program file I have...

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

void main()
{
     string name;
     MyStuff Stuff;

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

     Stuff.setName(name);
}

And I\'m gathering that applying \"using namespace std;\" in a header file is a no-no, and that to fully qualify is the \"better\" practice; such as std::cout << stuff << endl;

It is my understanding that in order to use a string, it must have the std namespace. Is that true?

If so, in the header file, is more \"pure/clean\" to do it as...

#include <string>

class MyStuff
{
     std::string name;
}

And, as I understand it currently, using namespace std; across all three files, specification, implementation, and program, essentially layers the three namespaces on top of each other, so if I separately declare string name; within each of the files, the compiler will not know which goes to what. Is that true?

I generally understand that being clear is a \"good\" thing to do, I am however a little unclear on the specificity of how, and I\'m most interested in the deeper \"why\" that underlies it all.

So my direct question is, in my example provided, what is the \"clearest\" way to describe the function both for the compiler and for industry \"standard\"? And, can you direct me to resources that more clearly delineate the reasoning and practical implementation of namespaces.


回答1:


Let's say I declare a class string myself. Because I'm a lazy bum, I do so in global namespace.

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

Some time later on, I realize that re-using some of your code would benefit my project. Thanks to you making it Open Source, I can do so:

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

string foo;

But suddenly the compiler doesn't like me anymore. Because there is a ::string (my class) and another ::string (the standard one, included by your header and brought into global namespace with using namespace std;), there's all kinds of pain to be had.

Worse, this problem gets promoted through every file that includes my header (which includes your header, which... you get the idea.)

Yes I know, in this example I am also to blame for not protecting my own classes in my own namespace, but that's the one I came up with ad-hoc.

Namespaces are there to avoid clashes of identifiers. Your header not only introduces MyStuff into the global namespace, but also every identifier from string and fstream. Chances are most of them are never actually needed by either of us, so why dragging them into global, polluting the environment?

Addition: From the view of a maintenance coder / debugger, foo::MyStuff is ten times more convenient than MyStuff, namespace'd somewhere else (probably not even the same source file), because you get the namespace information right there at the point in the code where you need it.




回答2:


Multiple instances of using namespace std; will not cause any ambiguity. The problem is that that statement imports all the names/types/functions of std into your namespace, and now if you want to name a class string for instance, you will hit into trouble. This is more likely to happen with functions like remove, erase, etc.

The use of it in headers is one level worse because that propagates to all the .cpps that header, without the awareness of person including it. Using it in .cpp atleast needs a conscious choice.

A more complete explanation can be got at Why is "using namespace std" considered bad practice?

An example of issues that might result from this can be found in How to use an iterator? where the OP defines a function distance, and keeps getting the wrong answer. Another example at Confusion about pointers and references in C++




回答3:


Namespace usings are for your convenience, not for you to inflict on others: Never write a using declaration or a using directive before an #include directive.

Corollary: In header files, don't write namespace-level using directives or using declarations; instead, explicitly namespace-qualify all names. (The second rule follows from the first, because headers can never know what other header #includes might appear after them.)

I generally understand that being clear is a "good" thing to do, I am however a little unclear on the specificity of how, and I'm most interested in the deeper "why" that underlies it all.

Below code snippets reflects why use using namespace in header file is bad:

// 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?
}

So in your example, simply this one is better:

#include <string>

class MyStuff
{
    std::string name;
};

Recommend book: C++ Coding Standards: 101 Rules, Guidelines, and Best Practices

and link: Google C++ coding guide



来源:https://stackoverflow.com/questions/14575799/using-namespace-std-in-a-header-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!