読者です 読者をやめる 読者になる 読者になる

名前空間

C++

プログラムを複数のソースファイルに分けていると、名前が重複してしまうことがなくもない・・・。
普通は、変数、関数、クラスはブロックごとに分かれているのでそういうことはほとんどない気もするが、他人のソースコードと組み合わせたときに、グローバル変数、クラス、クラス外の関数などは意図せず被ってしまうということはありえる・・・。

そこで、名前空間というさらに大きな概念でプログラムを分けていくことで、衝突を避ける・・・。

たとえば、test1.hが、

// クラスclass_test
class class_test{

  // publicメンバ
  public:

    // publicメンバ関数
    void print(); // 出力メンバ関数print

};

test1.cppは、

// ヘッダのインクルード
// 既定のヘッダ
#include <iostream> // C++標準入出力
// 独自のヘッダ
#include "test1.h" // "test1.h"のクラスclass_test

// class_testのメンバの定義.
// メンバ関数print
void class_test::print(){

  // 出力
  std::cout << "test1" << std::endl; // "test1"と出力.

}

だとして、test2.hが、

// クラスclass_test
class class_test{

  // publicメンバ
  public:

    // publicメンバ関数
    void print(); // 出力メンバ関数print

};

でtest2.cppが、

// ヘッダのインクルード
// 既定のヘッダ
#include <iostream> // C++標準入出力
// 独自のヘッダ
#include "test2.h" // "test2.h"のクラスclass_test

// class_testのメンバの定義.
// メンバ関数print
void class_test::print(){

  // 出力
  std::cout << "test2" << std::endl; // "test2"と出力.

}

とし、namespace.cppでは、

// ヘッダのインクルード
// 独自のヘッダ
#include "test1.h" // "test1.h"のクラスclass_test
#include "test2.h" // "test2.h"のクラスclass_test

// main関数の定義
int main(void){

  // オブジェクトの宣言
  class_test obj1; // class_testオブジェクトobj1

  // 出力
  obj1.print(); // obj1.printで出力.

  // プログラムの終了
  return 0;

}

とする・・・。
class_testがtest1.h/test1.cppとtest2.h/test2.cppの2箇所で定義されているので、コンパイルすると、

$ g++ -o namespace namespace.cpp test1.cpp test2.cpp
In file included from namespace.cpp:4:0:
test2.h:2:7: エラー: ‘class class_test’ が再定義されています
 class class_test{
       ^
In file included from namespace.cpp:3:0:
test1.h:2:7: エラー: ‘class class_test’ の前の定義
 class class_test{
       ^
$

再定義のエラーが出る・・・。
そごで、test1.h/test1.cppのclass_testを名前空間"test1"で囲む・・・。
test1.hは、

こういう感じでnamespace test1で囲む・・。

test1.cppは、

インクルードとか含めてしまうと、ややこしくなるので関数定義のところにとどめる・・・。

test2.h/test2.cppは名前空間"test2"で囲む・・・。

そして、

これで、"test1"のclass_testと"test2"のclass_testになったので、名前空間をクラス名の前に指定してやれば、再定義と認識されず、別々のものと認識される・・・。
namespace.cppで、

こんな感じでそれぞれの名前空間をclass_testの前に付けることで、別々のクラスとして認識される・・・。
コンパイルして実行すると、

$ vi namespace.cpp
$ g++ -o namespace namespace.cpp test1.cpp test2.cpp
$ ./namespace
test1
test2
$

test1とtest2の両方が出力されているので、別々のクラスとして認識されている・・・。

Sample/cpp/namespace/namespace/src/namespace at master · bg1bgst333/Sample · GitHub