C++プログラムでのヘッダの再定義エラーへの対処方法

このQ&Aのポイント
  • C++プログラムでのヘッダの再定義エラーへの対処方法をご教示ください。
  • C++プログラムで、クラス'H'を再定義しようとしてエラーが発生します。このエラーの対処方法を教えてください。
  • C++プログラムでヘッダのインクルード時に「クラス'H'を再定義しようとしています」というエラーが出力されます。このエラーを解消する方法を教えてください。
回答を見る
  • ベストアンサー

ヘッダのインクルード時のエラー

初歩的な質問で恐縮です。 以下のようなファイルの構成でc++のプログラムを組んでいます。 <header.h> class H { public: virtual void func() = 0; }; <fileA.cpp> #include "header.h" class A : public H { public: void func() {} }; <fileB.cpp> #include "header.h" class B : public H { public: void func() {} }; <main.cpp> #include "fileA.cpp" #include "fileB.cpp" int main() { A a; B b; a.func(); b.func(); return 0; } これをビルドしようとすると、「クラス"H"を再定義しようとしています」とエラーが出てコンパイルができません。理屈は分かるのですが、これの対処方法が分かりません。この場合、header.hはJAVAにおけるInterfaceのような役割としてそれを使うfileA.cpp、fileB.cppの両者にインクルードしておきたいのです。これはどのようにして対処すべきなのでしょうか?

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

  • ベストアンサー
  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

header.h にインクルードガードを追加する #ifndef COMMON_HEADER_H #define COMMON_HEADER_H (header.h の本体) #endif

taku17
質問者

お礼

ありがとうございました、無事解決しました。

関連するQ&A

  • [VC++]ヘッダファイルからの関数コール

    Formのボタンクリックイベント(Form.h)から 別ファイル(.cpp)の関数をコールしたいのですがうまくいきません、 どのようにすればよいでしょうか?ご教授お願いします。 1> : error C2144: 構文エラー : 'void' は ')' によって先行されなければなりません。 1> : error C2059: 構文エラー : ')' //----- main1.h #include <stdio.h> #include "Form1.h" namespace A { void main1(); } //----- main1.cpp #include <stdio.h> #include "main1.h" using namespace A; void main1() { //処理 } //----- Form1.h #include <stdio.h> #include "main1.h" void main1(void); namespace A { public ref class Form1 : public System::Windows::Forms::Form { public: private: System::Void btn_Click(System::Object^ sender, System::EventArgs^ e) { //★クリックイベントからmain1の関数コールしたい main1(void); } }; }

  • コンストラクタの順序?

    以下のソースに関して質問です。 /* library.h */ #pragma comment(lib, "library.lib") class A { public: A(); }; /* library.cpp */ #include "library.h" #include <list> class B { private: std::list<int> m_listi; public: void Func() { m_listi.push_back(0); //フリーズ return; } } g_CB; A::A() { g_CB.Func(); return; } /* test.cpp */ #include "library.h" A CA; int main() { return 0; } library.cppからlibrary.libをつくり、それをtest.cppで使用したところ、 ソースに示したところでプログラムがフリーズしてしまいます。 恐らくクラスBのm_listiが初期化される前にそれを使おうとしたためだと思います。 どうすればそれを避けられるでしょうか。。。

  • bccでエラー:メンバー関数は呼び出すかそのアドレスを~

    クラスのメンバ関数を、ある関数(実は qsort)の引数として渡したい と思っています。環境は OS:Windows XP コンパイラ:C++Builder6 に付属の bcc32.exe です。 下記のコード(t.cpp)をコマンドプロンプトで bcc32 t としてコンパイルすると「※1」の行で下のエラーになります。 「エラー E2235 t.cpp 29: メンバー関数は呼び出すか  そのアドレスをとらなければならない(関数 main() )」 どのように直せば良いでしょうか? -------------------------------------------------------- #include <stdio.h> #include <stdlib.h> class Aclass { public: void f(int); }; void Aclass::f(int x) { printf("classfunc %d\n", x); } void sub1(int x) { printf("sub-1 %d\n", x); } void call_func(void(*func)(int), int x) { func(2*x + 1); } void main(void) { call_func((void(*)(int))sub1, 11); Aclass *a = new Aclass; call_func((void(*)(int))a->f, -7); //※1 delete a; } -------------------------------------------------------- この掲示板、行頭の空白が削除されてしまいますねー。

  • error LNK2001について

    C++ の勉強中です。 error LNK2001問題がありました。問題点も分からないから、 分かった方に教えていただけないでしょうか? ソースも添付します。環境はVS2005 express edition まず、ヘッダファイルです。ファイル名は、myheader.h #ifndef __MYHEADER_H__ #define __MYHEADER_H__ #define includeshow(x) \ { \ s.show(x); \ } class Sample{ public: void show(char * parameter); }; extern Sample s; #endif //------------------------------------------------ 次に、Sample.cppです。 #include "myheader.h" #include <stdio.h> void Sample::show(char *parameter){ printf("in show func"); } //----------------------------------------------- 最後にTest.cppです。 #include "myheader.h" #include <stdio.h> int main(){ includeshow("ppppp"); } これで error LNK2001: 外部シンボル ""class Sample s" (?s@@3VSample@@A)" は未解決です。というエラーが出ています。 よろしくおねがいします。

  • Visual C++ ヘッダー情報の反映

    ヘッダー内の定義(の変更)が反映されないことがあります。 例えば、 "stdafx.h"において #define a 123 と定義して、関数項目main.cppとfunc.cpp両方でaを使うとします。 もちろんどちらも最初に#include "stdafx.h"とインクルードしています。 ですがdefine定義を#define a 456のように変更し実行すると、 main.cpp内ではa=456で動作し、func.cpp内ではa=123で動作する。 というような症状がしばしば現れます。 Visual stadio 2008でプログラミングしています。 c++ 6.0のときも同様の症状が現れていたのですが、何か問題があるのでしょうか? よろしくお願いします。

  • ヘッダーファイルのインクルード

    VC++6.0です。 ヘッダーファイルをincludeしていいかどうかは どのように決まるのでしょうか? classは、appとhogeの1種類があるとして、 app.h、app.cppとhoge.cpp、hoge.hの4つのファイルがあるとします。 1)appによるhogeのメンバの操作があって、その逆は無い場合 2)hogeもappのメンバを操作する場合 のそれぞれで教えてください。 最初、私は、そのclass内で別のclassのメンバ関数を 呼ぼうと呼ぶまいとincludeしてもかまわないと思っていました。 しかし、自分の作ったプログラムを検討したところ 1)の場合で、hogeのヘッダーに #include "app.h"と入れるとエラーになります。 hogeのcppファイルに#include "app.h"と入れてもエラーになります。

  • extern記憶クラス指定子を使う事について

    prg1.cpp----------------------------- #include<stdio.h> void func(void); int gg=5678; int main(void) { printf("main gg=%d\n",gg); func(); return 0; } ---------------------------------- prg2.cpp-------------------------- #include<stdio.h> extern int gg; void func(void) { printf("func gg=%d\n",gg); } ---------------------------------- 以上「prg1.cpp」と「prg2.cpp」という名前のふたつのファイルを作成し、「prg1.cpp」で宣言したグローバル変数を「prg2.cpp」で利用可能にしたいと思っています。 それには、「prg1.cppをコンパイルし、prg2.cppもコンパイルして、両者のオブジェクト(コンパイル後のファイル)をリンクする」と参考書には書いてあったのですが、どのようにしたらリンクされるのかわかりません。 prg.1cpp---------------------- #include<stdio.h> void func(void); int gg=5678; int main(void) { printf("main gg=%d\n",gg); func(); return 0; } #include<stdio.h> extern int gg; void func(void) { printf("func gg=%d\n",gg); } ------------------------------- 以上のように、「prg1.cpp」のファイルに1つにまとめれば、なぜかよくわかりませんが実行できました。 しかし「prg1.cpp」と、「prg2.cpp」をリンクさせてみたいので、教えていただけると嬉しいです。

  • VirtualとpImplの速度について

    どちらの使用するか迷っています。ご助言をお願いします。 インターフェイスだけ晒して、メンバ変数を完全に見えないようにするためには、pImplパターンがあると思います。 //-------------------------------------------------------- //header.h class Imp; class TestPImpl {   Imp*pImpl; public:   TestPImpl();   void Func(); }; //cpp.cpp class Imp {   int i; public:   void Func()   {    i++;   } }; TestPImpl::TestPImpl() {  pImpl = new Imp; } void TestPImpl::Func() {  pImpl->Func(); } //-------------------------------------------------------- 一方、次のようにやることも可能です(呼び名は知りません)。 //-------------------------------------------------------- //header.h class VirtualBase { public:   virtual void Func() =0; }; VirtualBase*CreateVirtualBase(); //cpp.cpp class VirtualDeri : public VirtualBase {   int i; public:   void Func()   {    i++;   } }; VirtualBase*CreateVirtualBase() {   return new VirtualDeri; } //-------------------------------------------------------- このほうが、変数も見えず見た目のすっきりします。 さらに、速度を計測をしました。 //-------------------------------------------------------- //main.cpp int main() {   const int MAX_CNT = 10000000;   VirtualBase*v = CreateVirtualBase();   long startTime = timeGetTime();   for(int i=0;i<MAX_CNT;i++)    v->Func();   printf("Vertial:[%d]\n",timeGetTime() - startTime);   TestPImpl*p = new TestPImpl();   startTime = timeGetTime();   for(int i=0;i<MAX_CNT;i++)    p->Func();   printf("pImpl:[%d]\n",timeGetTime() - startTime); } 結果 >Virtual[336] >pImp[594] //-------------------------------------------------------- 後者の方が、速度的には有利です。(本来ならば、出力されたアセンブリなどを見て、勝手に"省略"されたかを確認する必要があるのかもしれませんが、現状自分はアセンブリを読むことはできません。) ここで質問です。よりシンプルに、かつ速度的にも有利に見える後者ではなく、pimplパターンを使うメリットは何なのでしょうか? 初めてpimplパターンを知ったときの宣伝は、コンパイル時間の短縮でした。しかし、後者の方法もヘッダを書き変えずにメンバ変数を変更することは可能なので、このメリットは後者の方法でも同じことです。 このような方法をとりたいと思っているのは、コンパイル時間を短縮するためではなく、現在作成しているDLLのヘッダに一切の変数を書きたくなかったからです。 DLLにすると、上記の実験の結果が変化するかはまだ確認していません。(DLLにすることにより状況が変わるかもしれないと考えています。) 質問内容自体にも間違い含まれているかもしれません。合わせてご助言お願いします。 環境はXP SP2 , VC8です。

  • templateのエラー

    すいません、C++始めたばっかりなのですが、 以下のようなエラーが出て困っています。 ClusteringMain.obj : error LNK2001: 外部シンボル ""public: void __thiscall File2Array<double>::disp(void)" (?disp@?$File2Array@N@@$$FQAEXXZ)" は未解決です。 どなたかご教授ください。 環境はWindows XP, Visual Studio.NET 以下はソースです。 --------ClusteringMain.cpp------------ #include < iostream > #include"File2Array.h" using namespace std; int main() { cout << "Hello world" << endl; File2Array<double> test; test.disp(); return 0; } ---------File2Array.cpp----------------- #include"File2Array.h" template <class Type> void File2Array<Type>::disp(void) { cout << "aaaaa" << endl; } ---------File2Array.h------------------- #include<iostream> #include<fstream> using namespace std; #ifndef FILE2ARRAY_H #define FILE2ARRAY_H 1 template <class Type> class File2Array { private: Type var; public: void disp(void); }; #endif // #define FILE2ARRAY_H 1

  • 可変長引数をもつオーバライド関数について

    オーバライド関数について質問があります。 以下のようなクラスAとBがあります。 クラスAは基本クラスです。 クラスBはクラスAから導出しました。 ------------------------------------ CLASS A { public: virtual void func(char* p, ...); } ------------------------------------ CLASS B : public A { public: void func(char* p, ...); } ------------------------------------ メンバ関数の func() はオーバライド関数で、可変長の引数を持っています。 今、クラスBの func() の中で、クラスAの func() をコールするようにコーディングしました。 ----------------------------------- void B::func(char* p, ...) { : : A::func( ???? ) : : } ----------------------------------- ところが、クラスBの func()が受け取った引数を、そのままクラスAの func() に渡したいのですが、どうしたらいいのか分かりません。これって無理でしょうか? 教えて下さい。