グローバルスコープと内部リンケージ
C では通常、グローバルスコープに置かれた宣言や定義は他のオブジェクトから参照可能。つまり、あるソースで
int gVar;
とあれば、他のソースで
extern int gVar;
とすれば、リンカがこの2つを結合してくれる。しかし、間違って同じ名前のグローバル変数が複数あったりすると、リンクの結果がどうなるかは神のみぞ知る。
こういうことがないように、(なぜかデフォルトでは公開されてしまってるのを) static を修飾することで他の翻訳単位との結合を禁止できる。これを内部リンケージという。
しかし
によれば、 C++ ではこれは非推奨らしい。
これと同じことを実現するために、全ての(公開すべきでない)グローバル変数を無名名前空間に置くべきとしている。
つまり、
namespace // 名前空間名を書かない { int gVar; // "static" はいらない } // ";" はいらない
これで、このソース内でしか結合されない。無名なので外部からリンクしようにも指定できない。
また、同じ名前空間は離散的にかかれていても(ブロックが複数あって離れていても)1つの空間とみなされ、それが複数の翻訳単位(ソース)にまたがってても適用される。じゃあ無名名前空間も?
実は、無名名前空間はそれぞれの翻訳単位で別の空間とみなされる。要するにだれも教えてはくれないけど、こっそりと秘密の名前をもってて、ソース内ならそれを意識しなくても特別な記法で使えるというわけ。その特別な記法とは、スコープ解決演算子をつけないこと、つまり変数名(とか)をそのまま書けばいい。要するに、秘密の名前が using namespace
で宣言されているということ。
ちなみにスコープ解決演算子で何も書かない
::gVar
は、グローバルスコープにおける gVar を表すので、無名空間の中の gVar にはならないので注意し、暗黙の using
が行われているため、無名名前空間の gVar を指すことができる。(間違ったこと書いてました。信じた人はごめんなさい。)