19

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

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

そして、私は「名前空間stdを使用して」適用することを集めています。ヘッダーファイルではノーノーであり、完全に修飾することは「より良い」方法です。そのようなstd::cout << stuff << endl;

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

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

#include <string>

class MyStuff
{
     std::string name;
}

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

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

だから私の直接の質問は、提供された私の例では、コンパイラと業界の「標準」の両方の関数を説明するための「最も明確な」方法は何ですか?そして、名前空間の推論と実際の実装をより明確に描写するリソースに私を向けることができますか。

4

3 に答える 3

16

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

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

しばらくして、コードの一部を再利用することが私のプロジェクトに役立つことに気付きました。オープンソースにしてくれてありがとう、私はそうすることができます:

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

string foo;

しかし、突然、コンパイラは私を好きではなくなりました。::string(私のクラス)と別の (標準のクラスで::string、ヘッダーに含まれ、でグローバル名前空間に取り込まれるusing namespace std;)があるため、あらゆる種類の苦痛があります。

さらに悪いことに、この問題は、私のヘッダー(ヘッダーを含む)を含むすべてのファイルで促進されます。

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

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

追加:メンテナンスコーダー/デバッガーの観点からは、他の場所(おそらく同じソースファイルでさえない)で名前空間を作成foo::MyStuffするよりも10倍便利ですMyStuff。これは、コード内のその場所で名前空間情報を取得するためです。それが必要。

于 2013-01-29T05:00:40.363 に答える
12

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

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

より完全な説明は、 「名前空間stdの使用」が悪い習慣と見なされる理由を参照してください

これに起因する可能性のある問題の例は「イテレータの使用方法」にあります。ここで、OPは関数distanceを定義し、間違った答えを取得し続けます。C++でのポインタと参照に関するConfusionの別の

于 2013-01-29T04:48:49.767 に答える
2

名前空間の使用は、他の人に与えることではなく、あなたの便宜のためです。#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のルール、ガイドライン、およびベストプラクティス

およびリンク:GoogleC++コーディングガイド

于 2013-01-29T04:56:33.333 に答える