第一章:基礎知識
9.名前空間
これまでのサンプルではクラスの中の定義と同じ位置に関数の内容も書いてきましたが、例えばC++BuilderではTForm1のButton1Click関数を見ると、Unit1.hの方にクラスの定義が、Unit1.cppの方に、関数の内容が書かれています。
このUnit1.hというファイルはヘッダーファイルでこのファイルはUnit1.cppのファイルの上に書かれるようになります。
そのUnit1.cppの上に書くための記述が#include “Unit1.h”という表記で、この表記の位置にUnit1.hのファイルの内容がコンパイル時に自動的に挿入されてからコンパイルされます。
関数の書き方ですが、次の例を見てください。
void __fastcall TForm1::Button1Click(TObject *Sender) { }
これはTButtonのOnClickイベントを作成した状態のCPPファイルに書かれる内容です。
ここで今注目してほしいのは、TForm1::という表記ですが、この::というのはTForm1の中に定義されていますと示す物で、この::の事をスコープ演算子といい、この時のクラス名の事を名前空間と呼びます。
関数名を記述するとき、クラスの外部にクラスのメンバー関数の内容を書くときは、必ずこの名前空間を示す::を用いた記述をしなければなりません。
なぜクラスを使うのに->や.を使わないのかというと、->や.はクラスをメモリ上に展開したときに利用する物で、この名前空間はコンパイラが変数や関数の位置を認識するための物であり、そもそもの用途が違うという理由があります。
クラス名=名前空間と説明しましたが、名前空間はクラス名だけでなく、namespace 名前{};というコードブロックを用いることで、クラスとは関係の無い変数や関数にも名前空間を与えることが出来るようになっています。
クラス名は通常の型名と同じように変数の型として利用できますが、この通常のnamespaceを使った場合の名前は型名には出来ません。
namespace XXX{ int x; int func(){ return 10; } }; namespace ZZZ{ int x; }; XXX::x=100; ZZZ::z=500; Caption = XXX::x + XXX::func();
このサンプルはnamespaceコードブロックを利用した名前空間のサンプルです。クラスや構造体とは違い、通常の変数や関数、場合によってはクラスを分類で分けるために利用されます。
namespace内で宣言した名前の変数は、別の名前空間でも同じ名前の変数や関数を宣言できます。その変数を使うときは名前空間名::変数名という記述をしなければなりません。
そして、namespaceを使った名前空間の宣言はクラス名とは違い、重複して宣言を書くことが出来ます。
namespace aaa{ int x; }; namespace bbb{ namespace ccc{ int c; }; int x; }; namespace aaa{ int y }; aaa::x=40; aaa::y=30; bbb::x=50; bbb::ccc::c=100;
このようにnamespaceの名前が重複した状態でも問題はありませんが、重複した名前空間の中に同じ名前の変数を書くことは出来ません。重複した名前空間は一つの名前空間と認識されます。
名前空間bbbの中に名前空間cccが宣言されていますが、このように名前空間の中に名前空間を収めることも出来るようになっています。
名前空間に重複する変数や関数名がない場合、名前空間を書かなくてもいいようにする方法があります。それがusing namespaceという記述です。
namespace XXX{ int aa; int xx; }; using namespace XXX; int xx; aa=100; XXX::xx=50; ::xx=33;
using namespace XXX;によってXXX::の記述を省略しているのがaa=100;の表記です。
しかし、XXXの中にはxxという変数が宣言され、グローバル変数にも同じxxという変数が宣言されています。これではxx=100;としただけではどちらのxxの事かコンパイラが理解できません、この場合はxxについては名前空間を省略して書くことは出来ません。XXXの中の物はXXX::xx=50;、グローバル変数の場合は ::xx=33;という記述になります。