回答:
名前空間は本質的にパッケージです。これらは次のように使用できます。
namespace MyNamespace
{
class MyClass
{
};
}
次にコードで:
MyNamespace::MyClass* pClass = new MyNamespace::MyClass();
または、常に特定の名前空間を使用する場合は、次のようにします。
using namespace MyNamespace;
MyClass* pClass = new MyClass();
編集:bernhardruschの発言に従って、「using namespace x」構文をまったく使用しない傾向があります。通常、オブジェクトをインスタンス化するときに名前空間を明示的に指定します(つまり、最初に示した例)。
std
ますが、小さなライブラリを扱う場合、個人的にはそれほど重要ではないことがわかりました。多くの場合using namespace FooBario;
、特にライブラリからかなりの数の型を使用している場合は、だけを使用できます。
using namespace X;
可能であればヘッダーファイルで回避する必要があることに同意します。
mylibrary::endl
、自分の特別な改行シーケンスを表す以外に何も使用しません。つまり、なぜ名前を発明するのですか?
マークイングラムが名前空間を使用するための小さなヒントを既に言ったことをすべて避けるために:
ヘッダーファイルで「using namespace」ディレクティブを使用しないでください。これにより、このヘッダーファイルをインポートするプログラムのすべての部分のネームスペースが開きます。実装ファイル(* .cpp)では、これは通常大きな問題ではありません。ただし、関数レベルで「using namespace」ディレクティブを使用することを好みます。
名前空間は、名前の競合を回避するために主に使用されていると思います。コード構造を必ずしも整理するためではありません。主にヘッダーファイル/ファイル構造を使用してC ++プログラムを整理します。
より大きなC ++プロジェクトでは、実装の詳細を隠すために名前空間が使用されることがあります。
usingディレクティブに関する補足:一部の人々は、単一の要素に対してのみ「using」を使用することを好みます。
using std::cout;
using std::endl;
using std::cout;
は使用宣言です
using std::cout, std::endl;
using std::cout, endl;
using namespace x
別の名前空間内にある場合は、ヘッダーでを使用しても問題ありません。これは私がお勧めするものではありませんが、グローバル名前空間を汚染することはありません。
Vincent Robertは彼のコメントのとおりです。C++ではどのようにして名前空間を適切に使用しますか 。
名前空間は、名前の衝突を回避するために最低限使用されます。Javaでは、これは「org.domain」イディオムによって強制されます(自分のドメイン名以外は何も使用しないことが想定されているため)。
C ++では、モジュール内のすべてのコードに名前空間を与えることができます。たとえば、モジュールMyModule.dllの場合、コードに名前空間MyModuleを指定できます。MyCompany :: MyProject :: MyModuleを使用している他の場所を見ました。これはやり過ぎだと思いますが、全体として、私には正しいようです。
ネームスペースから現在のネームスペースに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 ;
}
多くの「using namespace std;」が表示されます。チュートリアルまたはサンプルコード。理由は、シンボルの数を減らして読みやすくするためです。
"名前空間stdを使用しています。" スコット・マイヤーズはお勧めしません(どの本を正確に覚えていませんが、必要に応じて見つけることができます)。
名前空間はパッケージだけではありません。別の例は、Bjarne Stroustrupの「The C ++ Programming Language」にあります。
「特別版」の8.2.8名前空間の構成では、2つの名前空間AAAとBBBを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() ;
}
異なる名前空間から選択シンボルをインポートして、独自のカスタム名前空間インターフェイスを構築することもできます。私はまだこれを実際に使用する方法を見つけていませんが、理論的にはクールです。
他の回答ではそれについての言及は見られなかったので、ここにカナダの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;
名前空間は単なる名前空間であると言っているすべての人々の言うことを聞かないでください。
これらはコンパイラによってインターフェイスの原則を適用すると見なされているため、重要です。基本的には、例で説明できます。
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 ++名前空間を使用する場合は、C ++名前空間を「インターフェイス」と見なし、インターフェイスの原則に留意する必要があります。
この動作の詳細な説明が必要な場合は、本 『ハーブサッターの例外C ++』を参照してください。
私が見たより大きなC ++プロジェクトでは、複数の名前空間(例:boostライブラリ)をほとんど使用していません。
実際にboostは大量の名前空間を使用します。通常、boostのすべての部分は内部の仕組みのために独自の名前空間を持ち、パブリックインターフェースのみをトップレベルの名前空間boostに配置する場合があります。
個人的には、単一のアプリケーション(またはライブラリ)内でも、コードベースが大きくなるほど、名前空間が重要になると思います。作業では、アプリケーションの各モジュールを独自の名前空間に配置します。
私が頻繁に使用する名前空間のもう1つの使用法(しゃれた意図はありません)は、匿名の名前空間です。
namespace {
const int CONSTANT = 42;
}
これは基本的に次と同じです:
static const int CONSTANT = 42;
ただし、静的ではなく匿名の名前空間を使用することは、C ++の現在のコンパイルユニット内でのみコードとデータを表示するための推奨方法です。
const int CONSTANT = 42;
名前空間スコープのトップレベルのconstは既に内部リンケージを意味しているため、どちらの例も同等です。したがって、この場合は匿名の名前空間は必要ありません。
また、名前空間に追加できることにも注意してください。これは例を示すとより明確になります。つまり、次のことが可能です。
namespace MyNamespace
{
double square(double x) { return x * x; }
}
ファイル内square.h
、および
namespace MyNamespace
{
double cube(double x) { return x * x * x; }
}
ファイル内cube.h
。これは単一の名前空間を定義しますMyNamespace
(つまり、複数のファイルにわたって単一の名前空間を定義できます)。
Javaの場合:
package somepackage;
class SomeClass {}
C ++の場合:
namespace somenamespace {
class SomeClass {}
}
そしてそれらを使用して、Java:
import somepackage;
そしてC ++:
using namespace somenamespace;
また、フルネームは、Javaの場合は「somepackge.SomeClass」、C ++の場合は「somenamespace :: SomeClass」です。これらの規則を使用して、名前空間に一致するフォルダー名を作成するなど、Javaで慣れているように整理できます。ただし、フォルダー->パッケージおよびファイル->クラスの要件はありません。そのため、パッケージと名前空間から独立して、フォルダーとクラスに名前を付けることができます。
@ マリウス
はい、一度に複数の名前空間を使用できます。例:
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があります。]
std
もありshared_ptr
、今では、その両方を使用boost
してstd
、使用しようとすると、名前空間が衝突しますshared_ptr
。
C ++の名前空間は実際には単なる名前空間であることに注意してください。これらは、パッケージがJavaで行うカプセル化を提供しないため、おそらくあまり使用しません。
std
よりも、名前空間をシンボルの前に付けることに慣れる方が良いusing
です。私はいつも書くように、std::cout
あるいはstd::string
今、それは私が今、彼らを呼んだから。私は決して書くつもりはありませんcout
。