C++には、名前空間という機能があります。
この機能を使うことで、プログラム内の識別子の衝突を回避することができます。
しかし、初心者にとっては名前空間の使い方がわかりにくい場合もあるかもしれません。
そこで本記事では、C++の名前空間について、サンプルコードを交えながら、わかりやすく解説していきます。
C++の名前空間とは何か
C++の名前空間とは、プログラム内で定義された識別子(変数や関数など)をグループ化するための仕組みです。名前空間を使用することで、同じ名前の識別子が衝突することを防ぐことができます。
例えば、以下のように2つのファイルで同じ名前の関数を定義した場合、
// file1.cpp
void func() {
// ...
}
// file2.cpp
void func() {
// ...
}
これらをコンパイルしてリンクすると、どちらのfunc()
が呼び出されるか不明瞭になるためコンパイルエラーになります。このような問題を解決するために、名前空間を使用します。
// file1.cpp
namespace ns1 {
void func() {
// ...
}
}
// file2.cpp
namespace ns2 {
void func() {
// ...
}
}
これらはそれぞれ異なる名前空間に属しているため、コンパイル時に正しくリンクされます。
また、名前空間はネストすることもできます。例えば、
namespace ns1 {
namespace ns2 {
void func() {
// ...
}
}
}
このようにネストされた名前空間では、ns1::ns2::func()
という形式で関数にアクセスします。
以上がC++の名前空間の基本的な説明です。次は名前空間を使用する使い方・注意点について解説していきます。
名前空間の使い方
名前空間は、C++においてグローバル名前空間を分割するための仕組みです。名前空間を使用することで、同じ名前の関数や変数が衝突することを防ぐことができます。
名前空間の宣言
名前空間は、以下のように宣言します。
namespace namespace_name {
// 名前空間内で定義される関数や変数
}
例えば、my_namespace
という名前の名前空間を作成する場合は以下のようになります。
namespace my_namespace {
int x = 10;
void print_x() {
std::cout << "x = " << x << std::endl;
}
}
このようにして定義されたmy_namespace
内では、x
やprint_x()
が定義されています。
これらの名前空間内に定義された変数や関数などは名前空間名::変数名・関数名
のように::
でつなげて記述します。
#include<iostream>
namespace my_namespace {
int x = 10;
void print_x() {
std::cout << "x = " << x << std::endl;
}
}
int main() {
int v = my_namespace::x;
my_namespace::print_x();
return 0;
}
x = 10
名前空間のネスト
名前空間はネストすることもできます。例えば、以下のように定義された場合、
namespace outer_namespace {
int x = 10;
namespace inner_namespace {
int y = 20;
void print_xy() {
std::cout << "x = " << x << ", y = " << y << std::endl;
}
}
}
外側の名前空間であるouter_namespace
内に、更に内側の名前空間であるinner_namespace
が定義されています。
この構造で変数yにアクセスしたい場合、outer_namespace::inner_namespace::y
のようにつなげて記述することでアクセス可能です。
名前空間のエイリアス
複雑な名前空間を扱う場合、短い別名を付けることができます。これは、「エイリアス」と呼ばれます。例えば、
namespace very_long_namespace_name {
// ...
}
// エイリアスを使ってvery_long_namespace_nameをvnに置き換える
namespace vn = very_long_namespace_name;
// vn内で定義された関数や変数にアクセス可能
vn::function();
vn::variable;
このようにしてエイリアスを使用することで、長い名前空間を短く書くことが出来ます。
以上がC++における名前空間の基本的な使い方です。
名前空間名の省略
usingを使用することで、そのソースファイル内で任意の名前空間名を省略して、名前空間内に定義された変数や関数などを直接使用することができます。例えば、以下のように記述します。
#include <iostream>
using namespace std; // std名前空間を使う
int main() {
cout << "Hello, world!" << endl; // std名前空間に含まれるcout, endlを使う
return 0;
}
ここでは、using namespace std;
と記述しているため、std名前空間にある変数・関数・クラスなどをstd::
を省略して記述できています。
ただし、名前空間のusingを過度に使用すると、コードの可読性が低下したり、名前空間のメリットである変数名や関数目の衝突(重複)が発生する可能性があります。
なのでusingの過度な使用はやめて、重複の可能性がある場合はstd::cout
のように名前空間を省略せずに書くようにしましょう。