標準C++ namespaceについて

以前ネット上で検索して見つからず、途方に暮れたのがこのnamespace(名前空間)だ。

2007/10/09 "using namespace seal::foo;"と書いていたのを"using seal::foo;"に修正。(Thanks to デフォルトの名無しさん)

名前空間とは

従来のC、及び標準化以前のC++の識別名はプログラムを構成する全要素中で一意である必要がある。例えば、stdio.hをインクルードすると、独自にFILEという型を作ることはできない。名前が衝突するため、コンパイルエラーとなるからだ。

標準ライブラリの型名や関数名は誰もが知ってるから、衝突が起こることはまずないが、違うベンダが開発したライブラリを組み合わせて使ったりすると、名前の衝突が起きる可能性がある。

そこでC++に導入されたのが名前空間である。名前空間は、空間に名前を付け、その中に型や変数、関数などを入れることで識別名の衝突を防ぐものだ。一番てっとり早い例が、最近の標準C++のライブラリに用いられている名前空間stdである。古いC++の教科書にあるコード

#include <iostream.h>
cout << "Hello, world!" << endl;

は、最新のC++では正しくない。標準C++のライブラリは名前空間stdの中に宣言されているので、正しくは

#include <iostream>
std::cout << "Hello, world!" << std::endl;

と書く。ちなみに、標準C++準拠のヘッダファイルは".h"がつかないことになった。".h"があるかどうかでライブラリの挙動を変える処理系もあるので注意が必要だ。

使い方

宣言

名前空間を宣言するには次のように書く。

// 名前空間 seal を定義する
namespace seal
{
    // ここに宣言する
    int foo();
    ...
};

// int foo()の定義

int seal::foo()
{
    ....
}

次のようにして関数fooを定義することもできる。

// 名前空間 seal を定義する
namespace seal
{
    // ここに宣言する
    int foo()
    {
        // int foo()の定義
        ....
    }
    ...
};

名前空間内へのアクセス

名前空間中の識別子にアクセスするには、次のように大域解決演算子::を使う。

// 関数fooを呼び出す
int a = seal::foo();

using

usingを使って、ある識別子をグローバルな名前空間に持ち上げることができる。こうするとその後は大域解決演算子を使う必要がない。

using seal::foo;
// 関数fooを呼び出す
int a = foo();

あるいは、名前空間全体をグローバルに引き上げることもできる。

using namespace seal; // seal全体の識別子が直接指定可能
// 関数fooを呼び出す
int a = foo();

先ほどのコードも、usingを使えばこう書ける。

#include <iostream>
using namespace std;

cout << "Hello, world!" << endl;

無名名前空間

特殊な名前空間として、「無名名前空間(no name namespace)」がある。これはnamespaceの後に名前を続けなかったときに作成される。無名名前空間は、そのモジュール(ファイル)内でのみ参照できる識別子を格納する。Cで言うところのグローバルなstatic変数と同じ様な扱いができる。

namespace
{
    int bar; // このモジュール内のみで使用可能
};

まとめ

名前空間について簡単に説明してみた。私自身標準C++の仕様を知ったのが数ヶ月前であり、名前空間の細かな規則や効果的な使い方を習得できたわけではない。また、標準C++で新しく生まれた仕様・変更された仕様は非常に多く、未だコンパイラメーカの対応もばらばらである。より詳しく知りたい方は書店で書籍をあさることをおすすめする。


戻る

Copyright (C) 2001-2007 Seal Software <sealsoft AT sealsoft.jp>