2009-02-07
ちょっとした実験.
namespace A {...}
namespace B { namespace A {...} ... }
のように,既に存在している名前空間 A と同じ識別子の名前空間を,別の名前空間 B の中に作ることはできるか? また,作られた場合どうやってアクセスするのか? を調べる.
最初の例:
#include <iostream>
namespace base
{
namespace A // base::A
{
int hoge (10);
}
namespace B
{
namespace A // base::B::A
{
void print(void)
{
using namespace std;
cout<< "hoge= "<< base::A::hoge <<endl;
}
}
}
}
このコードは問題なくコンパイルでき*1,
base::B::A::print();
とすれば print() 関数を呼び出せる.上のコードでは base::A::hoge のように hoge にアクセスしているが,以下のようなコードはエラーとなる:
cout<< "hoge= "<< hoge <<endl;
// error: 'hoge' was not declared in this scope
cout<< "hoge= "<< A::hoge <<endl;
// error: 'hoge' is not a member of 'base::B::A'
上のコードの,最初の A は base::A として,次の A は base::B::A としてコンパイラに認識されている. base::B::A::print において, hoge とした場合にも A::hoge とした場合にも base::B::A::hoge を意味することになるから,これらのようなエラーが発生するのだ. base::A::hoge のように正確に指定することで,最初の A の中の hoge にアクセスできる.
では,名前空間 base がなかったらどなるのか? 結論は ::A::hoge のようにアクセスすればいい.
#include <iostream>
namespace A
{
int hoge (20);
}
namespace B
{
namespace A
{
void print(void)
{
using namespace std;
cout<< "hoge= "<< ::A::hoge <<endl;
}
}
}
以下のような指定だとエラーとなる:
cout<< "hoge= "<< hoge <<endl;
// error: 'hoge' was not declared in this scope
cout<< "hoge= "<< A::hoge <<endl;
// error: 'hoge' is not a member of 'B::A'
base がない場合は,最初の A は無名名前空間の中に作られるので ::A としてコンパイラに認識され, B の中の A は ::B::A としてコンパイラに認識されるのである.
一番最初の例では,実は ::base::A::hoge という指定がもっとも正確だ.しかし共通の名前空間 base があるから先頭の :: を省略できたのだ.