237

私は、名前空間ではなくパッケージが使用されるJavaのバックグラウンドを持っています。私は、完全なオブジェクトを形成するために一緒に機能するクラスをパッケージに入れ、後でそのパッケージからそれらを再利用することに慣れています。しかし、今はC++で作業しています。

C ++で名前空間をどのように使用しますか?アプリケーション全体に対して単一の名前空間を作成しますか、それとも主要なコンポーネントに対して名前空間を作成しますか?もしそうなら、他の名前空間のクラスからどのようにオブジェクトを作成しますか?

4

16 に答える 16

171

名前空間は本質的にパッケージです。これらは次のように使用できます。

namespace MyNamespace
{
  class MyClass
  {
  };
}

次にコードで:

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

または、常に特定の名前空間を使用する場合は、次のように実行できます。

using namespace MyNamespace;

MyClass* pClass = new MyClass();

編集:bernhardruschが言ったことに従って、私は「using namespace x」構文をまったく使用しない傾向があります。通常、オブジェクトをインスタンス化するときに名前空間を明示的に指定します(つまり、最初に示した例)。

そして、以下で質問したように、好きなだけ名前空間を使用できます。

于 2008-09-03T12:57:13.900 に答える
121

すべてを言うのを避けるために、Mark Ingram はすでに名前空間を使用するためのちょっとしたヒントを言っています:

ヘッダー ファイルで「using namespace」ディレクティブを使用しないでください。これにより、このヘッダー ファイルをインポートするプログラムのすべての部分の名前空間が開かれます。実装ファイル (*.cpp) では、これは通常大きな問題にはなりませんが、私は関数レベルで "using namespace" ディレクティブを使用することを好みます。

名前空間は主に名前の競合を避けるために使用されると思いますが、必ずしもコード構造を整理するためではありません。主にヘッダーファイル/ファイル構造でC++プログラムを整理します。

大規模な C++ プロジェクトでは、実装の詳細を隠すために名前空間が使用されることがあります。

using ディレクティブに関する追加の注意: 一部の人々は、単一の要素に対してのみ「using」を使用することを好みます。

using std::cout;  
using std::endl;
于 2008-09-03T13:10:02.370 に答える
81

Vincent Robert のコメントは正しいです。C++ で名前空間を適切に使用するにはどうすればよいですか? .

名前空間の使用

名前空間は、少なくとも名前の衝突を避けるために使用されます。Java では、これは "org.domain" イディオムによって強制されます (自分のドメイン名以外は使用しないと想定されているため)。

C++ では、モジュール内のすべてのコードに名前空間を与えることができます。たとえば、モジュール MyModule.dll の場合、そのコードに名前空間 MyModule を指定できます。MyCompany::MyProject::MyModule を使っている人をどこかで見かけました。これはやり過ぎだと思いますが、全体として、私には正しいようです。

「使う」を使う

using は、1 つ (またはすべて) のシンボルを名前空間から現在の名前空間に効果的にインポートするため、細心の注意を払って使用する必要があります。

あなたのヘッダーはそれを含むすべてのソースを汚染するので(それはマクロを思い出させます...)、そしてソースファイルでさえ、グローバルスコープでインポートされるため、関数スコープ外の悪いスタイルであるため、ヘッダーファイルでこれを行うのは悪です名前空間からのシンボル。

「using」を使用する最も安全な方法は、選択したシンボルをインポートすることです。

void doSomething()
{
   using std::string ; // string is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   std::cout << a << std::endl ;
}

void doSomethingElse()
{
   using namespace std ; // everything from std is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   cout << a << endl ;
}

「名前空間 std を使用している」がたくさん表示されます。チュートリアルまたはサンプルコードで。その理由は、記号の数を減らして読みやすくするためであり、良い考えだからではありません。

「名前空間 std を使用 ;」Scott Meyers が推奨していません (正確にはどの本かは覚えていませんが、必要に応じて見つけることができます)。

名前空間の構成

名前空間はパッケージ以上のものです。別の例は、Bjarne Stroustrup の「The C++ Programming Language」にあります。

「特別版」の8.2.8 Namespace Compositionで、AAA と BBB の 2 つの名前空間を CCC と呼ばれる別の名前空間にマージする方法について説明しています。したがって、CCC は AAA と BBB の両方のエイリアスになります。

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

namespace CCC
{
   using namespace AAA ;
   using namespace BBB ;
}

void doSomethingAgain()
{
   CCC::doSomething() ;
   CCC::doSomethingElse() ;
}

独自のカスタム名前空間インターフェイスを構築するために、さまざまな名前空間から選択したシンボルをインポートすることもできます。私はまだこれの実用的な使い方を見つけていませんが、理論的にはクールです。

于 2008-09-17T09:56:31.250 に答える
78

他の回答ではそれについての言及は見られなかったので、ここに私の2カナダセントがあります:

「名前空間を使用する」トピックでは、便利なステートメントは名前空間エイリアスです。これにより、名前空間を「名前変更」して、通常は短い名前を付けることができます。たとえば、次の代わりに:

Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo;
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;

あなたは書ける:

namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally;
Shorter::TheClassName foo;
Shorter::AnotherClassName bar;
于 2009-10-21T13:19:01.980 に答える
57

名前空間は単なる名前空間であると言っているすべての人に耳を傾けないでください。

インターフェイスの原則を適用するためにコンパイラによって考慮されるため、これらは重要です。基本的に、例で説明できます。

namespace ns {

class A
{
};

void print(A a)
{
}

}

A オブジェクトを出力する場合、コードは次のようになります。

ns::A a;
print(a);

関数を呼び出すときに名前空間を明示的に言及しなかったことに注意してください。これがインターフェイスの原則です。C++ は、型を引数として受け取る関数をその型のインターフェイスの一部と見なします。そのため、パラメーターは既に名前空間を暗示しているため、名前空間を指定する必要はありません。

では、なぜこの原則が重要なのでしょうか? クラス A の作成者がこのクラスに print() 関数を提供しなかったとします。自分で用意する必要があります。あなたは優れたプログラマーであるため、この関数を独自の名前空間またはグローバル名前空間で定義します。

namespace ns {

class A
{
};

}

void print(A a)
{
}

また、コードは任意の場所で print(a) 関数の呼び出しを開始できます。数年後、作成者がクラスの内部構造を知っており、あなたのバージョンよりも優れたバージョンを作成できるため、作成者があなたのよりも優れた print() 関数を提供することを決定したと想像してください。

次に、C++ の作成者は、インターフェイスの原則を尊重するために、別の名前空間で提供されているものではなく、彼のバージョンの print() 関数を使用する必要があると判断しました。また、この print() 関数の「アップグレード」はできるだけ簡単にする必要があります。つまり、print() 関数の呼び出しごとに変更する必要はありません。そのため、C++ では名前空間を指定せずに「インターフェイス関数」(クラスと同じ名前空間にある関数) を呼び出すことができます。

そのため、C++ 名前空間を使用する場合は「インターフェイス」と見なし、インターフェイスの原則に留意する必要があります。

この動作のより詳しい説明が必要な場合は、Herb Sutter の書籍 Exceptional C++ を参照してください。

于 2008-09-07T01:26:58.920 に答える
36

私が見たより大きな C++ プロジェクトでは、複数の名前空間をほとんど使用していません (ブースト ライブラリなど)。

実際には、boost は大量の名前空間を使用します。通常、boost のすべての部分には、内部動作用の独自の名前空間があり、パブリック インターフェイスのみを最上位の名前空間 boost に配置できます。

個人的には、コードベースが大きくなればなるほど、単一のアプリケーション (またはライブラリ) 内でも名前空間が重要になると思います。仕事では、アプリケーションの各モジュールを独自の名前空間に配置します。

私が頻繁に使用する名前空間のもう 1 つの用途 (しゃれは意図していません) は、匿名名前空間です。

namespace {
  const int CONSTANT = 42;
}

これは基本的に次と同じです。

static const int CONSTANT = 42;

ただし、(静的ではなく) 匿名名前空間を使用することは、コードとデータが C++ の現在のコンパイル単位内でのみ表示されるようにするための推奨される方法です。

于 2008-09-07T00:31:00.520 に答える
20

また、名前空間に追加できることに注意してください。これは例でより明確になります。つまり、次のことができるということです。

namespace MyNamespace
{
    double square(double x) { return x * x; }
}

ファイル内square.h、および

namespace MyNamespace
{
    double cube(double x) { return x * x * x; }
}

ファイルでcube.h。これにより、単一の名前空間が定義されますMyNamespace(つまり、複数のファイルにわたって単一の名前空間を定義できます)。

于 2008-09-03T13:17:11.870 に答える
12

Java の場合:

package somepackage;
class SomeClass {}

C++ の場合:

namespace somenamespace {
    class SomeClass {}
}

そしてそれらを使用して、Java:

import somepackage;

そしてC++:

using namespace somenamespace;

また、完全な名前は、Java の場合は「somepackge.SomeClass」、C++ の場合は「somenamespace::SomeClass」です。これらの規則を使用すると、名前空間に一致するフォルダー名を作成するなど、Java で慣れているように整理できます。ただし、フォルダー->パッケージおよびファイル->クラスの要件は存在しないため、パッケージと名前空間とは別にフォルダーとクラスに名前を付けることができます。

于 2008-09-03T13:09:44.977 に答える
6

@マリウス

はい、一度に複数の名前空間を使用できます。たとえば、次のようになります。

using namespace boost;   
using namespace std;  

shared_ptr<int> p(new int(1));   // shared_ptr belongs to boost   
cout << "cout belongs to std::" << endl;   // cout and endl are in std

【2月 2014 -- (本当にそんなに長いのですか?): Joey が以下で指摘しているように、この特定の例は現在あいまいです。Boost と std:: がそれぞれ shared_ptr を持つようになりました。]

于 2008-09-03T13:08:02.967 に答える
5

たとえば、関数内に「using namespace ...」を含めることもできます。

void test(const std::string& s) {
    using namespace std;
    cout << s;
}
于 2008-09-03T14:59:01.360 に答える
3

一般的に言って、関数や型の名前が他のライブラリと競合する可能性があると思われる場合は、コード本体の名前空間を作成します。また、ブランドコード、alaboost ::にも役立ちます。

于 2008-09-03T13:00:19.070 に答える
3

アプリケーションにはトップレベルの名前空間を使用し、コンポーネントにはサブ名前空間を使用することを好みます。

他の名前空間のクラスを使用する方法は、驚くべきことにJavaの方法と非常によく似ています。「importPACKAGE」ステートメントに類似した「useNAMESPACE」を使用できます。たとえば、usestdを使用できます。または、「::」で区切られたクラスのプレフィックスとしてパッケージを指定します(例:std :: string)。これは、Javaの「java.lang.String」に似ています。

于 2008-09-03T13:00:50.457 に答える
3

C++ の名前空間は実際には単なる名前空間であることに注意してください。これらは、パッケージが Java で行うカプセル化を提供しないため、あまり使用しないでしょう。

于 2008-09-03T13:19:09.040 に答える
2

javaとC++のもう1つの違いは、C ++では、名前空間階層がファイルシステムのレイアウトを変更する必要がないことです。したがって、再利用可能なライブラリ全体を1つの名前空間に配置し、ライブラリ内のサブシステムをサブディレクトリに配置する傾向があります。

#include "lib/module1.h"
#include "lib/module2.h"

lib::class1 *v = new lib::class1();

名前が競合する可能性がある場合にのみ、サブシステムをネストされた名前空間に配置します。

于 2008-09-03T14:42:11.743 に答える
2

私は C# や Perl などと同じ方法で C++ 名前空間を使用してきました。これは、標準ライブラリのもの、サードパーティのもの、および独自のコードの間でシンボルを意味的に分離したものにすぎません。独自のアプリを 1 つの名前空間に配置し、再利用可能なライブラリ コンポーネントを別の名前空間に配置して分離します。

于 2008-09-03T13:38:25.593 に答える
-1

std :: cout

プレフィックス std:: は、名前 cout および endl が std という名前の名前空間内で定義されていることを示します。名前空間を使用すると、定義した名前とライブラリ内での同じ名前の使用との間の不注意な衝突を回避できます。標準ライブラリで定義されているすべての名前は stdnamespace にあります。std:: cout と書くと、スコープ演算子 (:: 演算子) を使用して、名前空間 std で定義されている名前 cout を使用したいことを伝えます。ライブラリから名前にアクセスする簡単な方法を示します。

于 2021-03-22T10:23:08.403 に答える