• ベストアンサー

 namespace定義の使い方

 こんにちは。 C++を勉強しています。 今回は、namespace宣言して使いたいのですが、ヘッダー内でnamespace宣言をすると重複してしまいます。namespaceで定義したものを他のファイルでも使いたい場合はどうすればいいでしょうか? よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

ヘッダファイルの2重読み込みではなく、ヘッダファイルで(宣言でなく)定義をしてしまったというケースでしたか。 この場合、2つの方法があります。 1.ヘッダファイルでは宣言だけを行い、ひとつの実行ファイル(のみ)で定義を行う ------- test.h ------ namespace TEST_SAPCE { extern int d; // ここは宣言 extern short h; } ------- test.cpp ------- #include "test.h" int TEST_SAPCE::d; // ここで定義 short TEST_SAPCE::h; int main() { TEST_SAPCE::d = 1; TEST_SAPCE::h = 0; return 0; } ------- sub.cpp ------- #include "test.h" void sub() { TEST_SAPCE::d = 1; TEST_SAPCE::h = 0; } 2.インクルードファイルでマクロを使い、定義と宣言を切り分ける方法 ------- test.h ------ #if defined(GLOBAL_HERE) #define GLOBAL #define init(x) = (x) #else #define GLOBAL extern #define init(x) namespace TEST_SAPCE { GLOBAL int d; GLOBAL short h init(10); } ------- test.cpp ----- // ひとつの実行ファイルだけ、test.h をinclude する前に、GLOBAL_HERE を定義する #define GLOBAL_HERE #inlcude "test.h" int main() { TEST_SAPCE::d = 1; TEST_SAPCE::h = 0; return 0; } ------- sub.cpp ------- #include "test.h" void sub() { TEST_SAPCE::d = 1; TEST_SAPCE::h = 0; }

DEADSPACE566
質問者

お礼

 なるほど、#defineを使ってソースファイルで定義することにより一度しか読み込まなくなるんですね。 それで重複定義を防げると。  大変参考になりました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • sygh
  • ベストアンサー率76% (42/55)
回答No.6

Visual C++限定で良いのであれば、 namespace Test { __declspec(selectany) int g_variableName; } のようにしてしまえばインスタンス生成が1回だけ行なわれるようになるので、ヘッダに宣言(Declaration)と定義(Definition)をまとめて記述できちゃいますが、それ以外のコンパイラの場合は他の回答者の方々が例示してらっしゃるように、ヘッダ側に宣言を記述(公開)して、ソースファイル側に実体を定義(実装)するようにします。 ただC++ではグローバル変数なんぞ使わないほうが無難です。 最悪でもstaticメンバーを使ってシングルトン実装にするのが定石かと。 ちなみに変数でなくconstを付けた定数であれば、C++の場合デフォルトで内部リンケージなので、ヘッダでも宣言と定義を記述できるようになっています。これにより、C言語でよく使われていたマクロ定数がほとんどの場面で不要になります。 namespace Test { const double PI = 3.141592653589793238; }

DEADSPACE566
質問者

お礼

 constを付けた場合だと重複定義にならないんですね。 参考書でconstを勧める意味が分かりました。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

既に答は出てるから蛇足だけど, 名前空間内だからといって特別なことはないんだよね. ヘッダで int x; とかやったらダメというのはいいよね? namespace で囲まれてるけど, 基本的にはこれと同じこと. 無名名前空間だとヘッダで定義しても二重定義にならないから話は違うけど, それで何を期待するのかはやっぱりわからん.

DEADSPACE566
質問者

お礼

 namespaceで括っていても、グローバル変数と変わりありませんね。

全文を見る
すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

グローバル変数の実体をヘッダーに定義しているのが原因なのでは ・・・ // Test.h namespace TEST_SAPCE {   extern int d;   extern short h; } として 外部定義ですとしておいて // Test.cpp namespace TEST_SAPCE {   int d;   short h; } といった具合に 実体をCPPファイルで行いましょう

DEADSPACE566
質問者

お礼

 ヘッダーに実体を書かくと重複してしまうようですね。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

何を言っているのかわかりません. 具体的かつ簡単な例は出せませんか?

DEADSPACE566
質問者

お礼

TEST.Hを使うヘッダーが幾つもある所為で、ERRORがでるようです。

DEADSPACE566
質問者

補足

簡単な例は、 //============TEST.H==========// #pragma once namespace TEST_SAPCE { int d; short h; } //============DOODLE.H(TEST.Hを使うヘッダー)==========// #include "TEST.h" ~ 以下略 ~ //========MAIN.CPP=======// #inlcude "DOODLE.h" int main() { int c; }

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

おそらくは、namespace が問題というより、単に、インクルードファイルの2十四見込みが発生しているだけという気がしますが。 この場合、インクルードガードと呼ばれる手法があります。 マイクロソフトの処理系だと、ヘッダファイルの先頭に #pragma once と書くだけです。 汎用的な方法としては、ヘッダファイルの先頭に #if !defined(ABCDEF) #define ABCDEF と書き、ヘッダファイルの最後に #endif を置く方法があります。 上の例で書いた、ABCDEF は、それぞれのヘッダファイルで一意になる名前(たとえば、プロジェクト名+ヘッダファイル名など)です。 このファイルが読み込まれた場合、最初は、(上の例では) ABCDEF が定義されていないので、ABCDEF を定義した上で、ヘッダファイル全体が有効になります。 2度目以降に読み込まれたとき、すでに ABCDEF が定義されているので、#if !defined() という条件に一致しなくなり、これ以降 #endif までがなかったことになります。

DEADSPACE566
質問者

お礼

ちなみにエラーはLNK2005です 下記はERROR出力です error LNK2005: "int TEST::d" (?d@TEST@@3HA) は既に XXXXX.obj で定義されています。 ヘッダーにはnamespaceで実体を定義するのはまずいみたいです。

DEADSPACE566
質問者

補足

#pragma once をしているのに、重複しているといわれます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 定義されているのにエラーになる

    閲覧ありがとうございます。 C言語のプログラムの話です。 ソースファイルaaa.cでstdio.hをincludeしています。 stdio.hには extern FILE _iob[_NIOBRW]; というのが定義されているにも関わらず、 コンパイルすると、 aaa.o:aaa.c:(.data+0x58): undefined reference to '_iob' というエラーが出ます。 aaa.cでは_iobに関する宣言はしていませんが、それを使うこともしていません。 ヘッダファイルでexternで宣言してるからかなと思い、ソースファイルにexternなしの宣言を書き足したら、コンパイルは通りました。 今回は元々既にあるプロジェクトの改修だったのですが、宣言を消したりしていません。 しかし、その部分は元々ヘッダファイルに宣言などしなくてもコンパイルが通ってました。 昔はヘッダファイルでexternで宣言してたらソースファイルではしなくてオッケーみたいな感じだったんですかね? 私自身、あまりよく分かってなくて文章もめちゃくちゃですみません。 不足している情報があればできる範囲でお伝えしますので、ご協力よろしくお願いいたします。

  • using namespace std;//?

    nubou C++で using namespace std; という宣言が使えるということなのですが ・namespaceとはなんでしょうか? ・stdとはなんでしょうか? ・このような宣言が必要な場面はどのようなときなのでしょうか? いずれかひとつでも結構です (質問に間違いがありましたので修正しました) よろしくお願いします

  • C++のnamespace stdについて

    C++のnamespace stdについて教えて下さい。 coutを使用する場合"iostream"をインクルードし、using namespaceでstd名前空間を使用します。 printfを使用する場合"cstdio"をインクルードし、using namespaceでstd名前空間を使用します。 どちらのインクルードファイルにもnamespace stdという風に同じ名前の名前空間を 使用しているのでしょうか? もしもそうだとしたらcstdio,iostreamの両方をインクルードしている場合 名前空間が競合してしまうのではないでしょうか? namespaceはjavaでいうパッケージにあたる物だと思っていたので、 これでは意味がないのではないかと思いました。 それとも意図的に同じ名前空間を定義している意味があるのでしょうか? C++を使い始めたばかりで戸惑っています。どなたかお答え頂ければありがたいです。

  • クラスのメンバ関数を別ファイルで定義したときのバグ

    C++ においてヘッダファイルで宣言したクラスのメンバ関数を別のソースファイルで定義して、コンパイルするとうまくいきません。エラーは出ないのですが、同名の何もしない関数としてコンパイルされているようなのです。クラスのメンバ関数を宣言したのと同じヘッダに書くとちゃんとコンパイルされます。 どうしてそうなるのか、いまいち原因がわかりません。

  • ヘッダーの多重定義での疑問です。

     Cで開発をしているのですが、ヘッダーファイルでの定義ではたとえば、int a と か double hoge とか定義して、そのヘッダーファイルを複数の cファイルが読み込むと多重定義になりますよね? hoge.h int a; // 多重定義 このヘッダーを複数の.cファイルに読み込む しかし、自分のプロジェクトだと、ヘッダーファイルにint aとかdouble hogeとか 定義してもエラーにならないんです。 ただし、int b = 10;のように代入すると多重エラー また、試しに新しくプロジェクトを作ってヘッダーで定義すると多重定義でエラーでした。

  • privateなnamespaceメンバ

    namespace内のメンバをprivateのようにしたいときは、無名名前空間を使うとあったのですが、ヘッダオンリーライブラリでこれを実現する方法はありませんか? 紹介されている方法 //hoge.h namespace Hoge{ void hoge(); } //hoge.cpp namespace Hoge{ namespace{ void hogeHelper(){} } void hoge(){hogeHelper();} } 上記の方法ではhoge.cpp以外からはhogeHelperにはアクセスできなくなるとのことです。 しかし、ヘッダオンリーライブラリで次のように書いている場合にHoge::hogeHelperとしてアクセスできてしまいます。 //hoge.h namespace Hoge{ namespace{ inline void hogeHelper(){} } inline void hoge(){hogeHelper();} } (ライブラリを書き換えない限り)hogeHelperへのアクセスを禁止する方法はありませんか?

  • ヘッダファイルにおける文字列リソース定義

    C言語(主にVC++)で開発をしていると、よく、 const char MSG_HELLO[] = "HELLO!"; のように、ヘッダファイル中で、文字列リテラルを定義します。 自分もいつのまにかこのようにリソース定義するようになっていましたが、初期の頃から疑問だったのは、extern宣言せずにchar配列を宣言しているから、コンパイラが最適化しなかったら、上記宣言のあるヘッダファイルを読み込んで、その定義を使った個所のあるソース分文字列リテラルがメモリ上に確保されてしまうのではないか、、?ということです。 つまり、本来なら const char* MSG_HELLO[] = "HELLO!"; とソースファイル中で定義し、ヘッダファイルには extern const char* MSG_HELLO; とすべきではないか、と思うわけです。ただ実際にこれをやっているとヘッダとソースの両方のメンテナンスが必要になるので、冒頭のように記述しているのだと思いますが。 この、本来なら下記のようにすべきだが、コンパイラの最適化(リソースのプール)を期待して最初のように書いている、という解釈は正しいでしょうか?

  • 関数の実体定義にヘッダファイルの2重定義防止方法が効かない?

    いつもお世話になっています。 MFCでCプログラミングをしています。 ヘッダファイルの2重定義防止のために、 ヘッダファイル全体を下記のように 囲みました。 <aaa.h> #ifndef AAA #define AAA #define PI 3.141592 void Func(); int wa(int a, int b){ return a+b; } #endif ビルドしたところ、 関数宣言(Func)や#define部分(PI)については、 2重定義が防止されているようなのですが、 関数の実体部分(関数wa)については、 2重定義防止機能が働かず、 ***.obj : error LNK2005: "int __cdecl wa(int a, int b)" は既に ***.obj で定義されています。 というリンクエラーが表示されます。 関数の種類や ヘッダファイル内の宣言の順番を いろいろ変えてみたのですが同じ結果でした。 ここで、このヘッダファイルの先頭に #pragma onceを使用すると このリンクエラーは回避されるのですが、 他コンパイラとの互換性の観点から、 #pragma once以外の方法で実現する必要があるので、 困っています。 URLを検索してみたのですが、 このような特殊な場合について記述されているものは 見つけられませんでした。 どなたか解決法又はヒントをご教示頂ければ ありがたいです。 よろしくお願いします。

  • PHP5のnamespace

    PHP5では名前空間をサポートしているという・・・。 http://www.atmarkit.co.jp/flinux/special/php5/php5c.html しかし、上記URLに記されている例を実行させようとしても namespaceを定義した所で文法エラーになります。 私、何か勘違いしていますか? もしくは何か設定でもあるのでしょうか? 利用しているPHPのバージョンは5.2.2です。

    • ベストアンサー
    • PHP
  • c#のマクロ定義について

    C言語でマクロ定義の場合以下のようにヘッダファイルに#defineで定義しますが、C#の場合どのようにすればいいのでしょうか。 C言語の場合 *** test.h *** #define TEST 5 C#の場合 public const int TEST = 5; //これでいいの? 専用のclassを用意するの? 初歩的な質問ですが宜しくお願い致します。

スキャン機能が正常に動かない
このQ&Aのポイント
  • スキャン機能が正常に動作せず、スキャン⇒PC⇒ファイル-フォルダ保存ができない問題が発生しています。
  • 最近、PCが不調になったため、PCを初期状態に戻した際にスキャン機能が正常に動作しなくなりました。
  • お使いの環境はWindows 10で、接続はUSBケーブルを使用しています。関連するソフト・アプリは特にありません。
回答を見る