名前空間


識別子の局所化

最初のほうで、名前空間について簡単に触れました
この章では、今まで曖昧にしていた名前空間について詳しく説明します

名前空間とは、プログラム内の変数や関数、クラスなどの識別子の住所です
全ての識別子がグローバルな位置にあると、それは名前の衝突の原因になります
事実、グローバルな識別子しか持たないプログラム言語では珍しくないエラーです

標準ライブラリや大規模プログラム用のモジュール群などを多用すると
それだけ識別子がグローバルな位置に増え、名前が衝突する可能性が高くなります
そのような場合に、この機能を用いるのです

名前空間の定義は namespace キーワードを使います
このキーワードの後のスコープで宣言された識別子は、指定された名前空間に局所化されます

namespace name {
...
}

name には、この名前空間の名前を指定します
名前空間の内部では、直接識別子にアクセスすることができますが
名前空間の外部からは、名前空間の名前をしていしなければ可視できません

名前空間の指定は、スコープ解決演算子を用いて指定します

name::member;

name は、名前空間を指定し member にはその名前空間内のアクセスしたい識別子を指定します
名前空間を定義することで、識別子を局所化することができます
#include<iostream>
using namespace std;

namespace Kitten {
	class Kitty {};
	char *str = "Kitty on your lap\n";
	void sakura() { cout << "Crad Captor SAKURA\n"; }
}

int main() {
	Kitten::Kitty obj;
	cout << Kitten::str;
	Kitten::sakura();

	return 0;
}
このプログラムには、Kitten という名前空間が存在します
この名前空間にアクセスするには、スコープ解決演算子を用います

名前空間によって、Kitten 内のクラス、変数、関数などは局所化し
そのため、名前空間の外部との名前の衝突の可能性がなくなります

ただし、名前空間は必ずグローバルな位置で定義しなければならず
関数などの特定のスコープのローカルな名前空間は認められません

同一の名前空間の定義は複数に分割することも可能です
名前が同じであれば、それらは一つの名前空間とされるので
ある名前空間の定義を、複数のファイルで行うことができます
#include<iostream>
using namespace std;

namespace Kitten {
	void Kitty();
	char *str = "Kitty on your lap\n";
}

int main() {
	Kitten::Kitty();
	return 0;
}

namespace Kitten {
	void Kitty() { cout << str; }
}
このプログラムでは、名前空間 Kitten が2ヶ所で作られています
これらは同じ名前空間として扱われるので、なんの問題もありません
下の Kitten は、同一の名前空間で定義されている変数 str へ直接アクセスしていますね


名前空間のネスト

名前空間は、スコープの外でなければ使えないと言いましたが例外があります
実は、名前空間はネストすることができるのです
つまり、名前空間の中に名前空間を含めることができます

階層化された名前空間へのアクセスは相対的になります
ある名前空間の中の名前空間へアクセスする場合、全ての名前空間の外であれば
名前空間のもっとも外側から順番に、目的の名前空間までスコープ演算子で指定します
名前空間の中からのアクセスであれば、当然自分の名前までは省略することができます
#include<iostream>
using namespace std;

namespace Kitten {
	namespace Kitty {
		char *str = "Kitty on your lap\n";
	}
	void print() {
		cout << Kitty::str;
	}
}

int main() {
	Kitten::print();
	cout << Kitten::Kitty::str;
	return 0;
}
名前空間 Kitten の中に別の名前空間 Kitty が存在します
Kitten から Kitty へのアクセスは、Kitty を明示してメンバを選択しますが
外部からは Kitten::Kitty::member というようにアクセスしていることに注目してください


無名名前空間

名前空間には、無名の名前空間があります
これは、C言語なら static なグローバル変数に等しいものです
この、無名の名前空間を無名名前空間と呼びます

通常、グローバル変数は全ての位置からアクセスすることができます
異なるファイル間であれば、extern キーワードを使ってアクセスしました

しかし、無名名前空間にアクセスできるのは同一ファイルのみです
別ファイルから無名名前空間にアクセスすることはできず
同一ファイルからであれば、グローバル変数としてアクセスすることができます
たとえ extern を用いても、他のファイルから無名名前空間にアクセスすることはできません
#include<iostream>
using namespace std;

namespace {
	char *str = "Kitty on your lap";
}

int main() {
	cout << str;
	return 0;
}
同一ファイル内では、グローバル変数 str として扱うことができます
ただし、無名名前空間で定義された変数 str は、他のファイルからアクセスすることができません
別ファイルからの extern char *str によるアクセスはできないのです

標準C++では、static より無名名前空間を使うことが推奨されます


namespace

namespace [identifier] { namespace-body }

宣言領域に名前をつけて、名前空間を割り当てます

identifier - 名前空間の名前を指定します。メンバを参照するのに用います
namespace-body - 名前空間の宣言領域です



前のページへ戻る次のページへ