• ベストアンサー

classの再定義エラーについて

C++初心者で初歩的な質問ですがよろしくお願いします。 【内容】  <test.h>  class testを定義  <test2.h>  class testを継承したclass test2を定義  <test3.h>  class testを継承したclass test3を定義  <test4.h>  class test2とclass test3で作成したインスタンスをメンバに持つclass test4を定義 【問題】  test2.hとtest3.hではclass testを継承するために#include "test.h"をしています。そして、test4.hではclass test2とclass test3を使うため#include "test2.h"、#include "test3.h"をしているのでredefinition of 'class test'というエラーが発生します。  このようなエラーを発生させずに上記の内容のものを実現させることは出来るのでしょうか?  ちなみにOSはTurboLinux8でコンパイラはg++です。よろしくお願いします。

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

  • ベストアンサー
  • anmochi
  • ベストアンサー率65% (1332/2045)
回答No.1

test.hの先頭に次の2行を追加してください。 #ifndef __TEST_H__ #define __TEST_H__ また、最後に次の行を追加してください。 #endif __TEST_H__ もちろん、test2.hやtest3.hもインクルードが重なる可能性がある場合は__TEST2_H__や__TEST3_H__で最初と最後に行を追加してあげましょう。これらは標準ヘッダファイル(stdio.hなど)で使われているテクニックです。 基本的にはヘッダファイルは必ずこれらの行でくくるようにしてあげると良いでしょう。 test.h -------- #ifndef __TEST_H__ #define __TEST_H__ ヘッダファイルの内容~~~ #endif __TEST_H__ -------- ↑こんな風にすると良いです。

aichi_soul
質問者

お礼

丁寧なご回答ありがとうございました。急いでいたので助かりました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

ヘッダファイルは, 何回 #include してもよいように書くのが基本です. そのためによく使われるのが #ifndef some_identifier #define some_identifier ここにヘッダファイルの本体を書く #endif という手法です. some_identifier をヘッダファイルごとに決めておけば (ヘッダファイルの名前から決めると楽) OK. このような手法はシステム標準のヘッダファイルでも使われていますので, そちらも参考にしてはどうでしょうか.

aichi_soul
質問者

お礼

本当に助かりました。ありがとうございました。

関連するQ&A

  • まずいClass定義への対応

    public class DataClass { public String data0=""; public String data1=""; .............................. public String data99=""; } と定義されたDataClassのインスタンスに文字列データxyzn(nはメンバーの通し番号)を入れるときに DataClass dataclass=new DataClass(); dataclass.data0="xyz0"; dataclass.data0="xyz1"; .............................. dataclass.data0="xyz99"; のように100行書き下さないでfor文を使うなどして短い行で済ませる方法はないでしょうか? ただしまずいDataClassの定義は変えられません DataClassのメンバー変数をArrayListや配列にしていれば問題ないのですが上記のように書き下されているのです

    • ベストアンサー
    • Java
  • include無しにclassが書けない

    粗末な質問タイトルで申し訳ありません。 Visual C++2010で、includeを書かずにclass宣言を行おうとすると「Error:PCH警告」が発生します。 この理由をご教授ください。 IntelliSense: PCH 警告: 適切なヘッダー停止位置が見つかりません。 というエラーメッセージが表示されるのですが、これはプロトタイプ宣言がないときに発生する警告らしいですね。私が書こうとしているソースコードを次に示します。 -----main.cpp---- class TestClass {}; int main(void) { return (0); } ----------------- このソースで、"class"の部分に赤波線が引かれて先述のエラーメッセージが表示されます。 このソースの先頭に#include<iostream>なり#include<stdlib.h>なり何かインクルードを記述すると警告はなくなります。 しかしクラスはその枠のみですし、ライブラリ関数も何も使用していないのでとくに必要なインクルードファイルも何もないと思うのですが、どうしてこのようなエラーが発生するのでしょうか。 あと、蛇足になりますが、本来はクラス宣言部分を別のヘッダーファイルに分けたいのです。 クラス宣言部分を別のヘッダーに分離してヘッダーの先頭に #pragma once を記述するか、分離したヘッダをmain.cpp内でインクルードしてもエラーは解消されます。 (何からもインクルードされなかったらエラーになる) もう何が何やらさっぱりわからないです><

  • [VC][ATL] 'ImageList_Read'が定義されていない!というエラーになるのは?

    VC++.NET 2002+WTL7.0で開発をしています。 アプリケーションウイザードでMFCアプリケーションを作成して、クラスの追加から「ATLのサポート」を追加します。そして、stdafx.hに #include "atlapp.h" #include "atlctrls.h" を記入すると 'ImageList_Read'が定義されていない というエラーになってしまいます。 とりあえずatlctrls.h内のエラー発生箇所をコメントアウトすることで対応しているのですが...どのようにしたらエラーがでないようにできるのでしょうか?よろしくお願いします。

  • std::stringの継承

    #include <iostream> #include <string> class test : public std::string{ }; int main() { test tmp; tmp = "aaa"; } tmp = "aaa";ですが test::operator =(char *) が定義されていないとでますが何故なんでしょうか? string(basic_string)でoperator=が定義されていると思うのですが、 演算子の定義は継承されないのでしょうか。

  • 継承について

    みなさま、どうかお知恵を貸して下さい。 javaを勉強中で、本を読みながら試しに動かしています。 現在、実現したい動作が実現可能かどうかを調べているところです。 そのため、環境やバージョン等は決まっておりません。 むしろ、実現可能な環境やバージョンがあれば、教えてください。 実現したい機能ーーーーーーーーーーーー 親クラスAにメンバーとメソッドを定義します。 Aを継承する子クラスBを定義します。 プログラム中で、A、Bのインスタンスを生成します。 そして、A、Bを継承するCのインスタンスを生成したいのです。 Cのメンバーやメソッドは、Bと同様のものです。 この場合、BのクラスからCのようなインスタンスを作成することは、可能なのでしょうか? ・・・Cを定義していないので、おそらく不可能かと思います。 やはりこういった場合、Aを継承しているBを継承するCクラスを定義しておく必要があると考えています。 では、Cを継承するD,Dを継承するE・・・というように、いくつ必要になるかわからない場合、最大数分継承したクラスを用意すべきでしょうか。 なぜ、そうしたいかというと、組織図のようなものを作成したいのですが、組織図を構成する人数は、ユーザーの任意としたいのです。 継承したクラスを用いれば、そのまま組織図の体系を表現できる気がしました。 質問が大雑把になってしまい、申し訳ないのですが、お力を貸していただければ幸いです。

    • ベストアンサー
    • Java
  • メンバインスタンスへのアクセス方法

    クラスインスタンスをメンバ変数として保持した時、その保持しているインスタンスのメンバや関数にはどのようにアクセスすればよいのでしょうか。 PHPの文法がまだよくわからないのですが、次のようにやると、エラーになってしまいました。 <?php class Test {  var $member;  public function __construct() {   $member = new Hello();  }  public function test() {   $this->member->world();  } } class Hello {  public function world() {   echo 'hello world';  } } $test = new Test(); // $test->test();はエラーとなってしまう。 $test->test(); ?>

    • ベストアンサー
    • PHP
  • VC++ のコンパイルエラーについて

    現在、解説書に記載されているコードをVC++でコンパイルできるか試しながらC++を独習中です。エラーの原因と対応が分からず困っております。どなかたご教示よろしくお願いします。 日付を表示するプログラムで米国表示か英国表示にするか列挙型の宣言と静的メンバーをヘッダーファイルに記載し、フラッグの定義と初期化をするプログラムをコンパイルしました。 ---クラス定義(ファイル名:date.h)--- #include <iostream.h> class date{ ----------------------- enum Lang {USA, UK}; static Lang format; public: ----------------------- }; ---メンバー関数定義(ファイル名:date.cpp)--- #include <string.h> #include <ctype.h> #include <stdlib.h> #include "date.h" ----------------------- Lang date::format = USA; ----------------------- ---------------------------------------- このファイルをコンパイルした結果、下記のエラーメッセージが表示されました。 エラー発生箇所は上記「Lang date::format = USA;」でした --------------------構成: date - Win32 Debug-------------------- コンパイル中... date.cpp date.cpp(17) : error C2501: 'Lang' : 識別名を宣言するのに、型が指定されていません。 date.cpp(17) : error C2239: 無効なトークン 'tag::id' が 'Lang' の宣言の後にあらわれました。 date.cpp(17) : error C2321: 構文エラー : 予期しない 'date::format' です。 cl.exe の実行エラー date.obj - エラー 3、警告 0 ----------------------------------------------------------------------------- エラーの原因と解決方法が分かりません。 よろしくお願いします。

  • コンパイルエラー

    //test.cpp #include<iostream> #include<string> class test { string hoge; public: test(string str); void method() const; } 14行目  test::test(string str) : test(hoge){} void test::method() const { std::cout << "test" << std::endl; } int main() { string s; std::cout << "名前を入力してください。" << std::endl; std::cin >> s; test aaa(s); aaa.method(); } コンパイルしようとすると下記エラーになります。 エラー E2303 test.cpp 7: 型名が必要 エラー E2139 test.cpp 7: 宣言に ; がない エラー E2293 test.cpp 10: ) が必要 エラー E2147 test.cpp 14: 引数宣言は 'string' で始められない エラー E2111 test.cpp 14: ここでは型 'test' は定義できない エラー E2136 test.cpp 14: コンストラクタには戻り型は指定できない エラー E2316 test.cpp 14: 'test::test(int)' は 'test' のメンバーではない エラー E2451 test.cpp 22: 未定義のシンボル string(関数 main() ) エラー E2379 test.cpp 22: ステートメントにセミコロン(;)がない(関数 main() ) エラー E2451 test.cpp 24: 未定義のシンボル s(関数 main() ) *** 10 errors in Compile *** ■1.型名が必要 →string hoge;と宣言してる箇所でエラー発生。 …stringと宣言してるのになぜでしょうか… ■2.宣言に";"がない →string hoge;と宣言してる箇所でエラー発生。 …";"つけてるのですが… ■3.")"が必要 →test(string str);の行でエラー発生。 …")"はどこで必要なのでしょうか ■4.引数宣言はstringでははじめられない →test::test(string str) : test(hoge){}の行でエラー発生。 …C++って引数をstringで受け取れない…?どういうことでしょうか などなど疑問がいっぱいあるのですが、どこが間違っているのかよくわかりません…ご指導よろしくお願いします。

  • 名前空間でビルドエラー(LNK2005)

    C++の名前空間について勉強しています。 ソースを組んでビルドしようとしたところ、以下のようなエラーが表示されました。 > error LNK2005 "int test::count" は既に main.obj で定義されています。 > fatal error LNK1169: 1つ以上の複数回定義されているシンボルが見つかりました。 変数が多重定義(?)されているというエラーであることはわかるのですが、 その対処法が分からず困っています・・・。 わかる方がいればアドバイスください。 よろしくお願いします。 --------------------------------------- ○main.cpp #include "ns.h" int main(){  test::hoge(); } ○ns.h #pragma once namespace test {  int count;  void hoge(); } ○ns.cpp #include <iostream> #include "ns.h" void test::hoge(){  std::cout << "hoge()が呼ばれた" << test::count++ << "回目" << std::endl; }

  • c++におけるtemplateについて

    c++の自作templateを関数宣言部と関数定義部とで、ファイルを分割する事を考えているのですが、エラーが出てtemplateをincludeすることが出来ないでいます。 例えば、 <ファイル:test.H> #ifndef test_H #define test_H #include <iostream> template<class T> class test { private: int row_, col_; public: test( int , int ); }; #endif <ファイル test.C> #include "test.H" template<class T> test<T>::test(int a, int b) :row_(a), col_(b) { std::cout << "コンストラクター" << std::endl; } <ファイル main.C> #include "test.H" #include<iostream> int main() { test a( 3, 3) return 0; } のようにtemplateファイルを分割した場合、 undefined reference to `test<double>::test(int, int)' collect2: ld returned 1 exit status のようなエラーがでます。 書籍:新c++言語入門・シニア編(下)の29章には「export」を関数定義部に付ければ良いような記述がありましたが、エラーを解決することが出来ませんでした。 main.Cにて、test.Cをインクルードするとこの問題を回避することが出来るのですが・・・。 そもそもtemplateは上記のように宣言部と定義部とを別々のファイルにすることはできないのでしょうか?

専門家に質問してみよう