18章 名前空間

http://www.geocities.jp/ky_webid/cpp/language/018.html

名前空間です。

定義した名前空間に属する変数や関数などを定義することができます。

とにかくこれは例を見たほうがはやいです。さっそく実装してみましょう。

#include <iostream>

namespace sample {
    int num;
}

int main () {
    sample::num = 100;
    
    std::cout << sample::num << std::endl;
    
    return 0;
}
$ main
100

namespaceというものを使って、そのブロック内で変数を定義すると上記のようにsample::numといった感じでアクセスすることができます。

簡単に言えば接頭辞付で変数を定義しているようなもんですね。sample_numとかみたいな感じで。

では自分で接頭辞付きを徹底するのと、名前空間を使うのと何が違うのかというと、人的なミスをしにくいというのが考えられます。

また、変数名が長くなるのも防げます。

そしてなんといってもusingが使えるというのが一番大きな違いですね。

usingの使い方は二種類あります。

usingディレクティブとusing宣言です。

まずはusingディレクティブを見てみましょう。

#include <iostream>

int main () {
    using namespace std;
    
    cout << "foo" << endl;
    
    return 0;
}
$ main
foo

このようにusing namespace stdとやると、名前空間stdに存在する関数や変数などのstd::を省略することができるよういなります。

とても便利ですね。

次にusing宣言を見てみましょう。

#include <iostream>

int main () {
    using std::cout;
    
    cout << "foo" << std::endl;
    
    return 0;
}

こちらの方法ではstd::coutだけstd::を省略することができるようになるということです。なのでendlの方はちゃんとstd::endlとしないとコンパイルエラーとなります。

さて、ここまで名前空間の挙動を見てきました。

そこでひとつ疑問があります。今まで名前空間を使わずに変数や関数を宣言していましたが、これらはどこの名前空間に属しているんでしょうか?

答えはグローバル名前空間です。

具体的にどんな値なのか?

それは「」です。何も名前がない名前空間となります。

名前空間sampleの変数numであれば、「sample::num」でアクセスできます。

名前空間がない変数のnumであれば、同じ理由から「::num」でアクセスできるということです。

そしてさらにC++の初期状態では「using namespace 名前無し」が初めから定義されているのでわざわざ「::num」とかかなくても「num」と書くことができていたというわけなのです。

#include <iostream>

// グローバル変数のnum
int num;

int main () {
    // ローカル変数のnum
    int num = 200;
    
    // グローバル変数のnumと::numは同じものを指している
    ::num = 100;
    
    // ローカル変数のnumを表示
    std::cout << num << std::endl;
    
    // グローバル変数のnumを表示
    std::cout << ::num << std::endl;
    
    return 0;
}
$ main
200
100

名前空間ってすごく便利ですね。今後はじゃんじゃん使っていきたいと思います。

ただしひとつだけ注意しないといけないことがあります。

例えば別の名前空間でたまたま同じ変数名が存在していた場合に、それらの名前空間をusingで読み込ませるとコンパイルエラーになってしまいます。

#include <iostream>

namespace sample1 {
    int num;
}

namespace sample2 {
    int num;
}

int main () {
    using namespace sample1;
    using namespace sample2;
    
    // これはsample1かsample2かどっちのnumなのか判断つかない
    num = 100;
    
    return 0;
}
$ cl /W4 /EHs main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(16) : error C2872: 'num' : あいまいなシンボルです。
        'main.cpp(8) の可能性があります : int sample2::num''
        または 'main.cpp(4) : int sample1::num'

ということなので、using使うときは名前の衝突が少ないusing宣言の方をなるべく使ったほうがいいかもしれません。

stdのように標準に定義されている名前空間なんかはusingディレクティブでもいいとは思いますが。