C++名前空間完全マスター:関数名の競合を防ぐ
同じクラスに同じ名前「Zara」の2人の生徒がいる状況を考えてみましょう。それらを区別するには、住んでいる地域が異なるなら地域名、または母親や父親の名前など、名前とともに追加情報を使用する必要があります。
同じ状況がC++アプリケーションでも発生し得ます。例えば、xyz() という関数を持つコードを書いていて、同じ関数 xyz() を持つ別のライブラリが利用可能な場合、コンパイラはあなたのコード内でどちらのバージョンの xyz() 関数を参照しているのか判断できません。
名前空間 はこの困難を克服するために設計され、異なるライブラリで利用可能な同じ名前の類似関数、クラス、変数などを区別するための追加情報として使用されます。名前空間を使用すると、名前が定義されるコンテキストを定義できます。本質的に、名前空間はスコープを定義します。
名前空間の定義
名前空間定義は、キーワード namespace に続けて名前空間名で始まります:
namespace namespace_name {
// コード宣言
}
名前空間対応版の関数や変数を呼び出すには、名前空間名を (::) で前置します:
name::code; // codeは変数または関数
名前空間が変数や関数などのエンティティをスコープする仕組みを見てみましょう:
Live Demo#include <iostream>
using namespace std;
// 最初の名前空間
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
// 2番目の名前空間
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
int main () {
// 最初の名前空間から関数を呼び出し
first_space::func();
// 2番目の名前空間から関数を呼び出し
second_space::func();
return 0;
}
上記コードをコンパイルして実行すると、以下の結果が得られます:
Inside first_space Inside second_space
using ディレクティブ
名前空間の前置きを避けるために、using namespace ディレクティブも使用できます。このディレクティブは、以降のコードが指定された名前空間の名前を使用することをコンパイラに伝えます。したがって、名前空間は以降のコードで暗黙的に適用されます:
Live Demo#include <iostream>
using namespace std;
// 最初の名前空間
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
// 2番目の名前空間
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
using namespace first_space;
int main () {
// 最初の名前空間から関数を呼び出し
func();
return 0;
}
上記コードをコンパイルして実行すると、以下の結果が得られます:
Inside first_space
『using』ディレクティブは、名前空間内の特定の項目を参照するためにも使用できます。例えば、std 名前空間で使用したいのが cout だけであれば、以下のように参照できます:
using std::cout;
以降のコードでは cout を名前空間なしで参照できますが、std 名前空間の他の項目は依然として明示的に指定する必要があります:
Live Demo#include <iostream>
using std::cout;
int main () {
cout << "std::endl is used with std!" << std::endl;
return 0;
}
上記コードをコンパイルして実行すると、以下の結果が得られます:
std::endl is used with std!
using ディレクティブで導入された名前は通常のスコープルールに従います。名前は using ディレクティブの位置から、ディレクティブが見つかったスコープの終わりまで可視です。外部スコープで同じ名前で定義されたエンティティは隠蔽されます。
不連続な名前空間
名前空間はいくつかの部分で定義でき、そのため名前空間は個別に定義された部分の合計で構成されます。名前空間の個別の部分は複数のファイルに分散できます。
したがって、名前空間の1部分が別のファイルで定義された名前を必要とする場合、その名前は依然として宣言されていなければなりません。以下のような名前空間定義を記述すると、新しい名前空間を定義するか、既存の名前空間に新しい要素を追加します:
namespace namespace_name {
// コード宣言
}
ネストされた名前空間
名前空間はネストでき、1つの名前空間の中に別の名前空間を定義できます:
namespace namespace_name1 {
// コード宣言
namespace namespace_name2 {
// コード宣言
}
}
ネストされた名前空間のメンバには、解決演算子を使用してアクセスできます:
// namespace_name2のメンバにアクセスするには using namespace namespace_name1::namespace_name2; // namespace_name1のメンバにアクセスするには using namespace namespace_name1;
上記文で namespace_name1 を使用している場合、namespace_name2 の要素がスコープ内で利用可能になります:
Live Demo#include <iostream>
using namespace std;
// 最初の名前空間
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
// 2番目の名前空間
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
}
using namespace first_space::second_space;
int main () {
// 2番目の名前空間から関数を呼び出し
func();
return 0;
}
上記コードをコンパイルして実行すると、以下の結果が得られます:
Inside second_space
C言語
- C++演算子完全ガイド:算術・代入・関係・論理・ビット演算子と実例
- C++コメント完全ガイド:読みやすく保守しやすいコードのためのベストプラクティス
- C++クラステンプレート完全ガイド:実践的なジェネリックプログラミング
- C++プログラミング言語:概要と主要機能
- C++定数とリテラル完全解説:型、構文、ベストプラクティス
- C++演算子完全ガイド:種類、使い方、ベストプラクティス
- C++数値型完全ガイド:実践的な使い方と数学関数
- C++リファレンス完全理解:重要概念とポインタとの違い
- C++名前空間完全マスター:関数名の競合を防ぐ
- C++テンプレート完全ガイド:ジェネリックプログラミングの基礎
- C++プリプロセッサ完全解説:ディレクティブがコードをどう形作るか