web-dev-qa-db-ja.com

名前空間stdを使用します。ヘッダーファイル内

だから、私は仕様ファイルに次のものを持っています

#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);
}

そして、「namespace stdを使用して」を適用することを収集しています。ヘッダーファイル内はno-noであり、完全に修飾することは「より良い」慣行です。といった std::cout << stuff << endl;

文字列を使用するためには、std名前空間が必要であると私は理解しています。本当?

もしそうなら、ヘッダファイルでは、それを行うためのより「純粋/クリーン」です...

#include <string>

class MyStuff
{
     std::string name;
}

そして、私が現在理解しているように、名前空間stdを使用しています。 3つのファイルすべて、仕様、実装、およびプログラム全体で、基本的に3つの名前空間を互いの上に重ねるので、個別にstring name;各ファイル内で、コンパイラはどちらが何に行くのかを知りません。本当?

一般的に、明確であることは「良い」ことだと理解していますが、具体的な方法については少し不明確であり、その根底にあるより深い「理由」に最も関心があります。

だから私の直接的な質問は、私の例では、コンパイラと業界の「標準」の両方について関数を説明する「最も明確な」方法は何ですか?また、名前空間の推論と実用的な実装をより明確に説明しているリソースに案内していただけますか。

15
RebelPhoenix

クラスstringを自分で宣言するとします。私は怠惰なお尻なので、グローバル名前空間でそうします。

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

しばらくして、yourコードの一部を再利用するとプロジェクトにメリットがあることがわかりました。オープンソースにしていただきありがとうございます。

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

string foo;

しかし、突然、コンパイラは私を好きではなくなりました。 ::string(私のクラス)とanother::string(標準のもので、ヘッダーに含まれていて、 using namespace std;)を使用したグローバル名前空間では、さまざまな苦痛が伴います。

さらに悪いことに、この問題は、myヘッダーを含むすべてのファイルを通じて促進されます(ヘッダーが含まれています...

はい、わかっています。この例では、自分の名前空間にある自分のクラスを保護しないことにも責任がありますが、それは私が特別に思いついたものです。

名前空間は、識別子の衝突を避けるためにあります。ヘッダーはMyStuffをグローバル名前空間に導入するだけでなく、stringおよびfstream。それらのほとんどが実際に私たちのどちらにも必要とされない可能性があるので、なぜそれらをグローバルにドラッグして環境を汚染するのでしょうか?

追加:メンテナンスコーダー/デバッガーの観点から、foo::MyStuffMyStuffの10倍便利です。他の場所に名前空間が付けられています(おそらく同じソースファイルでもありません) )、ネームスペース情報は、コードの必要な場所で取得できるためです。

11
DevSolar

using namespace std;の複数のインスタンスは、あいまいさを引き起こしません。問題は、そのステートメントがstdのすべての名前/タイプ/関数をネームスペースにインポートすることです。たとえば、クラスにstringと名前を付けたい場合、問題が発生します。これは、削除、消去などの機能で発生する可能性が高くなります。

ヘッダーでのの使用は1レベル悪化します。これは、ヘッダーを含むすべての.cppsに伝搬します。 .cppでそれを使用するには、少なくとも意識的な選択が必要です。

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

これから生じる可能性のある問題の問題の例は、 イテレータの使用方法 にありますOPは関数distanceを定義し、間違った答えを出し続けます。 別の例at C++でのポインターと参照に関する混乱

10
Karthik T

名前空間の使用はあなたの便宜のためであり、他人に与えることではありません:#includeディレクティブの前にusing宣言またはusingディレクティブを記述しないでください

当然のこと:ヘッダーファイルでは、ディレクティブや宣言を使用して名前空間レベルを記述しないでください。代わりに、すべての名前を明示的に名前空間で修飾します。 (2番目のルールは最初のルールに従います。これは、ヘッダーが他のヘッダー#includeの後に表示される可能性があるものを決して認識できないためです。)

一般的に、明確であることは「良い」ことだと理解していますが、具体的な方法については少し不明確であり、その根底にあるより深い「理由」に最も関心があります。

以下のコードスニペットは、ヘッダーファイルでの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++コーディング標準:101ルール、ガイドライン、およびベストプラクティス

とリンク: Google C++コーディングガイド

2
billz