【C++】namespaceとは?|名前の衝突を防ぐ仕組みを解説

C++

今回は、C++でよく出てくる「namespaceとは何か」について解説していきます。

「namespaceって何?」
std::std ってそもそも何?」
「名前の衝突を防ぐって、どういうこと?」

こんな疑問はありませんか?

プロジェクトが大きくなると、別々の場所で同じ名前の関数やクラスを作ってしまい、ぶつかることがあります。namespaceは、その衝突を防いでコードを整理するための仕組みです。実は毎回書いている std::std も namespaceの1つです。

この記事を読み終えると、あなたはnamespaceの意味・使い方・using宣言の注意点・初心者がハマりやすいミスをしっかり理解できると思いますので、ぜひ最後まで読んでいただけると嬉しいです。

namespaceとは?

namespace(名前空間)とは、名前をグループにまとめて、衝突を防ぐ仕組みです。同じ Init という関数でも、別の namespace に入れておけば区別できます。

#include <iostream>

namespace Audio {
    void Init() { std::cout << "サウンド初期化n"; }
}

namespace Input {
    void Init() { std::cout << "入力初期化n"; }
}

int main() {
    Audio::Init(); // どっちのInitか明確
    Input::Init();
    return 0;
}
サウンド初期化
入力初期化

同じ Init でも、Audio::InitInput::Init で区別できました。名前空間::名前 の形で呼ぶのが基本です。

なぜnamespaceが必要?

理由は、大きなプロジェクトやライブラリでは名前がぶつかりやすいからです。自分のコードと外部ライブラリで同じ名前の関数があると、どちらを呼んでいるのか分からずエラーになります。namespaceで区切っておけば安心です。

ファイルを分割する仕組みと合わせて使うと整理しやすくなります(インクルードガードの記事もどうぞ)。

using宣言と注意点

毎回 std:: を書くのが面倒なとき、using namespace std; と書くと省略できます。ただしこれはヘッダファイル(.h)には書かないのが鉄則です。

#include <iostream>
using namespace std; // .cpp の中ならOK

int main() {
    cout << "std:: を省略できるn";
    return 0;
}
std:: を省略できる

ヘッダに書くと、そのヘッダを読み込んだ全ファイルに影響してしまい、namespaceのメリットが台無しになります。使うなら .cpp の中だけにしましょう。

【重要】私が実際にnamespaceで困った体験談

個人開発で、あるサンプルのヘッダに using namespace std; が書いてあるのに気づかず自分のヘッダでも同じことをしていたら、別ライブラリの countstd::count がぶつかって「あいまいだ」というコンパイルエラーが大量発生しました。

原因は、ヘッダで using namespace をしたせいで名前が混ざったこと。ヘッダからは using namespace を全部消し、必要な所で std:: を明示するようにしたら、きれいに解決しました。「ヘッダで using namespace は禁物」と体で覚えた出来事です。

namespace使用時のよくある失敗例と対処法

①ヘッダにusing namespaceを書く

体験談のとおり、名前が混ざって衝突します。ヘッダでは書かない、が鉄則です。

②「名前空間::」を付け忘れる

namespaceの中の関数は Audio::Init() のように呼びます。付け忘れると見つからないエラーになります。

③namespaceを深くネストしすぎる

入れ子が深すぎると A::B::C::D::func() のように長くなり読みにくくなります。階層は浅めに保つのがおすすめです。

注意点

  • using namespaceヘッダに書かない(.cppの中だけ)
  • 呼ぶときは 名前空間::名前 を基本にする
  • ネストは浅めに、機能ごとに分けると整理しやすい

まとめ

  • namespaceは名前をまとめて衝突を防ぐ仕組み
  • std も namespaceの一種
  • using namespace は便利だがヘッダでは使わない
  • 機能ごとに分けると、大きなプロジェクトでも整理しやすい

namespaceは、コードを整理して名前の衝突を防ぐ縁の下の力持ちです。まずは AudioInput のように、機能ごとに区切るところから使ってみてください。

関連記事