2-4. 名前空間

公開日: 14:43 2. 応用編/2-4. 名前空間

Zaraという同じ名前の人物が2人いる状況を考えてみます。この2人を間違いなく区別する必要がある時、名前に加えて違う地域に住んでいるのであれば地域、両親の名前など、追加情報を使わなければなりません。

C++でも同じ状況は起こりえます。例えば、xyz()という関数をコーディングし、別のxyz()関数を持つライブラリが利用可能だとします。コンパイラはコード内で参照しているxyz()関数がどちらのバージョンか知る方法がありません。

名前空間(ネームスペース)はこの煩わしさを解消するために設計され、異なるライブラリで同じ名前が利用可能なとき、同様の関数、クラス、変数などを区別するために追加情報のように使われます。本質的には、名前空間はスコープを定義します。

名前空間の定義

名前空間の定義はnamespaceキーワードで始まり、後ろに名前空間名が続きます。
namespace namespace_name {
   // コード宣言
}

関数や変数の有効化された名前空間を呼び出すには、名前空間名をつけます。
name::code;  // codeは変数または関数
名前空間が変数や関数の実体をどのように評価するか確認しましょう。
#include <iostream>
using namespace std;

// first name space
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
}
// second name space
namespace second_space{
   void func(){
      cout << "Inside second_space" << endl;
   }
}
int main ()
{
 
   // Calls function from first name space.
   first_space::func();
   
   // Calls function from second name space.
   second_space::func(); 

   return 0;
}

上のコードをコンパイルし実行すると、次のような結果が得られます。
Inside first_space
Inside second_space

ディレクティブの利用

using namespaceディレクティブで名前空間の付与を回避することができます。ディレクティブはコンパイラに、続くコードが指定された名前空間の名前を使うことを伝えます。名前空間は次のコードのように暗示されます。
#include <iostream>
using namespace std;

// first name space
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
}
// second name space
namespace second_space{
   void func(){
      cout << "Inside second_space" << endl;
   }
}
using namespace first_space;
int main ()
{
 
   // first name spaceから関数を呼び出し
   func();
   
   return 0;
}

上のコードをコンパイルし実行すると、次の結果が得られます。
Inside first_space

ディレクティブの利用は名前空間内の特定の要素を参照することにも使われます。例えば、coutをstd名前空間で使うつもりならば、次のように参照することができます。
using std::cout;

次のコードは名前空間を付与せずにcoutを参照していますが、std名前空間の他の要素は明示される必要があります。
#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ディレクティブからディレクティブが見つかるスコープの最後まで見えます。スコープの外で定義された同じ名前の実体は見えません。

非連続の名前空間

名前空間は複数の箇所で定義することができます。そのため、名前空間はその別途定義された部分の集合で構成されます。名前空間の分割部分は複数のファイルに分散することができます。

よって、名前空間の一部が別のファイルで定義された名前を必要とする場合、その名前が宣言されている必要があります。次の名前空間定義は、新しい名前空間を定義するか、既存のものに新しい要素の追加を追加します。
namespace namespace_name {
   // コード宣言
}

入れ子名前空間

名前空間は名前空間の中に別の名前空間を定義し、入れ子構造とすることが可能です。
namespace namespace_name1 {
   // コード宣言 
   namespace namespace_name2 {
      // コード宣言 
   }
}
スコープ解決演算子を使って入れ子構造の名前空間のメンバにアクセスできます。
// namespace_name2のメンバへアクセス
using namespace namespace_name1::namespace_name2;
// namespace:name1のメンバへアクセス
using namespace namespace_name1;

上の構文においてnamespace_name1を使っている場合、次のようにしてnamespace_name2の要素を利用できるようにします。

#include <iostream>
using namespace std;

// first name space
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
   // second name space
   namespace second_space{
      void func(){
         cout << "Inside second_space" << endl;
      }
   }
}

using namespace first_space::second_space;
int main ()
{
 
   // second_spaceから関数を呼び出し
   func();
   
   return 0;
}
上のコードをコンパイルし実行すると、次の結果が得られます。
Inside second_space
  • ?±??G???g???[?d????u?b?N?}?[?N???A

0 件のコメント :

コメントを投稿