• ベストアンサー

No.799238の続き

listに構造体を格納するというのは確かに出来たのですが、 ヘッダーファイルとcppファイルに分けて書くときにはどうなるのでしょうか? 私がやってみると、ヘッダーファイルは、 classの中にorderの定義を書く: ・・・ class{ ・・・ struct order{ double price; double no; double quantity; }; list < struct order > B; list < struct order > ::iterator iteB; ・・・ } あるいは、 classの外にorderの定義を書く: ・・・ struct order{ double price; double no; double quantity; }; class{ ・・・ list < struct order > B; list < struct order > ::iterator iteB; ・・・ } いずれにおいてもコンパイル失敗しました。

noname#108554
noname#108554

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

  • ベストアンサー
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.1

なぜここにきてclassがでてきたのかわかりませんが、 ヘッダーファイルをわける方法と classの中に構造体をいれる話は関係ありません。 とりあえず前のソースを無理矢理分けてみましたが、、、 *****ヘッダファイルtest.h***** #include <iostream> #include <cstdlib> #include <stdio.h> #include <list> #include <vector> using namespace std; struct order{ double price; double no; double quantity; }; class xxx{ public: list < struct order > B; list < struct order > ::iterator iteB; }; *****ソースファイルtest.cpp***** #include "test.h" void main() { xxx C; list < struct order > B; list < struct order > ::iterator iteB; struct order Player1={1.1,10.,0.9}; C.iteB=C.B.begin(); C.B.insert(C.iteB,Player1); struct order Player2={1.,11.,0.9}; double limit=Player2.price; C.iteB=C.B.begin(); if(C.B.size()>0){ while((*C.iteB).price>=limit && C.iteB!=C.B.end())iteB++; } } 普通クラスにするならpublicではなく privateにし、内部処理するメンバ関数をもたせます。

noname#108554
質問者

お礼

ようやくできました。ありがとうございました。

その他の回答 (3)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

list < struct order > B; ここでの<>に囲まれた「struct order」はテンプレート引数です。 list < struct <order> > B; となると、structという命令自体がテンプレート引数を持ち、 order型というテンプレート引数を受け取っているということに なってしまいます。 で、実際の例ですが listクラスは、ヘッダファイル「list」の中で、 template<class _Ty, class _A = allocator<_Ty> > class list { ・ ・ void push_back(const _Ty& _X) ・ ・ と宣言されています。(VC++6.0のヘッダファイルより) list<int> x; のように変数を宣言をすると、listのクラス定義やソースに含まれる _Tyがすべてintに置き換えられてコンパイルされます。 intがstruct orderになっても同じことです。 構造体だから、クラスだからということで何も変わりません。 list<int> x; の場合、 x.push_back( 0 ); x.push_back( 1 ); x.push_back( 2 ); とすることで、listの最後に要素が追加されていきます。 ここでlist<int>クラスがpush_backメソッドから受け取っているのは あくまでも値のみ(実際には参照が)です。 となると、当然次のソースも問題ありません。 int i = 0; x.push_back( i ); i++; x.push_back( i ); i++; x.push_back( i ); 呼び元の変数iがどこのアドレスで領域が確保されていようが 知ったこっちゃないということです。 ようは、変数内の値のみがlistには格納されているということです。 listは、_Ty型の値を内部で管理しているということです。 で、ここでintをstruct orderに変えてみて何が変わるか? ということです。 はっきりいって、listは何も変わりません。 intの時と同様、 list<struct order> x; で、_Tyがstruct orderに置き換えられ、コンパイルされるだけです。 もちろんintのときと変わらないんですから、 struct order i = {0, 0}; x.push_back( i ); i.a = 1; i.b = 10; x.push_back( i ); i.a = 2; i.b = 20; x.push_back( i ); これで何も問題はありません。 listのpush_backメソッドには、値を渡すだけでいいのですから。 で、ここが本題なのですが、 以前、ibm_111さんはnewしてdeleteにこだわっていましたよね。 newして確保した領域を破棄してはいけない例を次に示します。 list<struct order *> x; struct order * p; p = new strunct order; p->a = 0; p->b = 0; x.push_back( p ); //delete p; p = new strunct order; p->a = 1; p->b = 10; x.push_back( p ); //delete p; p = new strunct order; p->a = 2; p->b = 20; x.push_back( p ); //delete p; こうした場合は、それぞれnewで確保したpを破棄してはいけません。 この場合は、listで管理しているのはstruct t *であるので、 構造体のアドレスのみを管理しているからです。 そのアドレスが指し示すstruct tのメンバの値まではlistが 管理をしていないため、deleteしてはいけないわけです。 ibm_111さんがdeleteにこだわったのは、list(以前はvector)で 管理している内容が、newで確保した領域そのものだという 思いからだという気がするんですけど、違いますか?

noname#108554
質問者

お礼

ありがとうございました。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

>>テンプレートがなんだか理解されてますか? > >だいたい理解しましたが、実際に使ってみたことはありません。 なにを言ってるんですか。 ibm_111さんが使っているlistやvector、 これこそテンプレートで作成されたライブラリである STLこと標準テンプレートライブラリです。 しっかり使ってるじゃないですか。 >テンプレートの理解と構造体の格納がどのようにつながるのか分かりません。 厳しいことを言いますが、テンプレートを理解することが できない限り、STLを使いこなすことはできません。 list < struct order > B; まさか、この記述、<>に囲まれた「struct order」が ただのクラスの引数だなんて思ってないですよね。

noname#108554
質問者

お礼

訂正します。 >>テンプレートがなんだか理解されてますか? > >だいたい理解しましたが、実際に使ってみたことはありません。 だいたい理解しましたが、自分でテンプレートを作ったことはありません。 >まさか、この記述、<>に囲まれた「struct order」が >ただのクラスの引数だなんて思ってないですよね。 いや、思ってます。それ以上の意味があるのですか?

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

横やりですけど・・・ >listに構造体を格納する テンプレートがなんだか理解されてますか? いろいろと試行錯誤されているようですが、 まず基本から理解したほうがいいと思いますよ。 前の質問では、 list < struct <order> > B; というテンプレートを理解していれば絶対にしない記述をされているので心配なのですが。 http://okweb.jp/kotaeru.php3?q=791495 でも結局途中で締め切ってしまったようですし。 で、 >いずれにおいてもコンパイル失敗しました。 #includeの記述の仕方が正しくないだけでしょう。 おそらく。 sha-girlさんの回答のように、ヘッダファイル内に必要な#includeを書いておけばいいかと。

noname#108554
質問者

お礼

ありがとうございます。 >テンプレートがなんだか理解されてますか? だいたい理解しましたが、実際に使ってみたことはありません。 しかし、 >list < struct <order> > B; >というテンプレートを理解していれば絶対にしない >記述をされているので心配なのですが。 テンプレートの理解と構造体の格納がどのようにつながるのか分かりません。 「~をvector、listに格納する」という意味のコードに対する 私の統一的な理解はまだ完成していません。

関連するQ&A

  • listに構造体を格納

    似たような質問を続けてしまって申し訳ないんですが、 listに構造体を格納するサンプルプログラム: #include <iostream> #include <cstdlib> #include <stdio.h> #include <list> #include <vector> using namespace std; void main() { struct order{ double price; double no; double quantity; }; list < struct <order> > B; list < struct <order> > ::iterator iteB; struct order Player1={1.1,10.,0.9}; iteB=B.begin(); B.insert(iteB,Player1); struct order Player2={1.,11.,0.9}; double limit=Player2.price; iteB=B.begin(); if(B.size()>0){ while((*iteB).price>=limit && iteB!=B.end())iteB++; } } を作ってみました。 が、コンパイルエラーになってしまいます。 list < struct <order> > B; が怪しいと思い、いろいろ試したのですが どうしてもコンパイルが通りません。 どのようにすればよいでしょうか?

  • テンプレートクラス内のテンプレートクラス(インナークラス)のメソッドを実装ファイルで定義したい

    現在、ヘッダファイル内で下記のようなクラスを宣言・定義しています。 // test.h template < typename T1 > struct A {   template < typename T2 > struct B   {     B( A const& arg ) { ... }   }; }; テンプレートクラスが入れ子になっていて、Bのコンストラクタが引数としてAを取っています。 しかし現状ではコンパイルがとんでもなく遅くなってしまうので、 Bのコンストラクタは宣言のみとし、別途実装ファイル(test.cpp)に定義を書きたいと思っています。 ところがメソッドのシグネチャをどう書けばよいのか分からなくなってしまいました。 苦し紛れに // test.cpp template < typename T1, typename T2 > A<T1>::B<T2>::B( A<T1> const& arg ) { ... } などと書いてみましたが、違うようです。 解決方法はありますでしょうか? 環境はVC7.1かVC8でコンパイルできればよいです。 よろしくお願いいたします。

  • 複数ファイルによる共通の外部変数定義について

    初歩的な質問なのですが、今各関数をファイルごとに分けて記述しようとしています。 ここで詰まっているのでできればご教授お願いします ファイル構成は プログラムファイル main.cpp sub.cpp ヘッダーファイル  myheader.h(main.cppとsub.cpp両方でインクルード) ヘッダーファイルには両方のプログラムファイルで使う変数が定義してあります。 それでmain.cppとsub.cpp両方で同じ変数を使いたいのですがコンパイルエラーが発生してしまいます。 内容はsub.obj側で「i(共通のループカウンタ)はmain.objですでに定義されています」というものです。 とにかく私のやりたいことはヘッダーに外部変数を定義して両方のプログラムファイルで使いたいというものです。 もしかしたらファイルを分けるにも何か設定が必要なのでしょうか? 私はただ[プロジェクト]→[プロジェクトに追加]→[新規作成]でソースファイルを作っているだけなんですが・・・ 上記の状態を回避する方法はあるのでしょうか?

  • ポインタによる包含&ヘッダにincludeしない、 場合でtemplateの定義に…

    class Bの宣言をしているヘッダ中で class A; を、前方宣言し、そのポインタだけを持たせ、ソースファイルのほうにclass Aの中身が分かるように、#includeして、ソースファイルに関数の実装やstatic変数の定義を書いていた、とします。 しかし、templateを使う関数についてはコンパイル時に解決できないといけないので、それだけはヘッダに持ってきました。 その時 includeが一切書かれていない、class Bのヘッダ内において class Aのメンバを参照するようなコードを書いたとき クラス外、クラス内、いずれに書いても 正常にコンパイルできました。 通常の関数では当然無理なので、もともとtemplateがコンパイル時解決を強要するものなのでそういう仕様にしててくれてると考えられますが 1.これは、C++の標準仕様でしょうか?それとも処理系依存でしょうか? あと、templateに関して 2.特殊化ならソースにかけるのは標準仕様でしょうか?それとも処理系依存でしょうか?

  • ヘッダファイルと構造体

    typedef struct{ float x; float y; float z; }Point; typedef struct { struct Point p1; struct Point p2; }Rect; とヘッダファイルに入力しコンパイルしてみると struct Point p1; struct Point p2; のPointが未定義の構造体とエラーが出ます。 どのように書けばいいのでしょう??

  • c++でのヘッダーファイルの循環参照

     c++言語においての質問です.  A, Bという二つのクラスを作ったとします.  宣言は.h,実装は.cppで行っています. 【A.h】 class A{ //内容 public: B ConvertB(); }; 【B.h】 class B{ //内容 public: A ConvertA(); };  上のように,クラスAではクラスBを返すメソッド. クラスBではクラスAを返すメソッドを実装したいとします.  しかし,単純に 【A.h】に #include "B.h" 【B.h】に #include "A.h" などとすると当然循環参照になってエラーになりますよね? ...とは言っても, 【A.cpp】や【B.cpp】にインクルードした所で, ヘッダ側でエラーが起きてしまいます.  そこで,私の場合は... 【A.h】の先頭に class B{ConvertAで用いるメソッド}; 【B.h】の先頭に class A{ConvertBで用いるメソッド};  というようにする事でなんとかエラーを避けています.    ...しかし,この方法ではAやBのクラスの定義を修正する場合に, 2つのファイルのヘッダを書き換えなければならなくなります. A, B, C, D...などとクラスが増えていくと, 一つのヘッダーファイルに4つも5つもクラスの定義を書かなければなりませんし, クラスのメソッドの定義を一つ変えようとしただけでも, 複数のヘッダの内容をいじらないといけません.  非常に読みにくいコードになってしまうのです.  そこで,もう少しスマートに実現する方法は無いでしょうか?  JavaやC#を使えば簡単に解決するのですが...ライブラリの関係でC++を使わなければ ならないのです.  もしくは,このような相互変換?のクラスを作る場合はみなさんはどのようにして ヘッダーファイルの循環参照を避けているのでしょうか?  例えば様々な形式の色空間のクラスなどだったら... RGBクラス YCrCbクラス HSVクラス ...など  このようなクラスを作った後で,RGBをYCrCbに変換出来るようにしたり, その逆へも変換出来るようにしたいのです.  それともこのような変換が出来るクラスを作る事は間違っているのでしょうか?    よろしくお願いします.

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

    初歩的な質問で恐縮です。 以下のようなファイルの構成で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の両者にインクルードしておきたいのです。これはどのようにして対処すべきなのでしょうか?

  • テンプレートクラスとSTLを利用したMyListクラス

    こんにちは。STLのリストを使い自分だけのMyListクラスを作ろうとしたのですが、コンパイルできません。 エラーメッセージは警告 std::list<T>::iterator' : 依存名は型ではありません。 とでます。 ご教授お願いします。 #include<list> #include<iterator> template <class T> class CMyList { public: CMyList(); //virtual ~CMyList(); //bool HasNext(); //T Next(); //void Pushback( T t ); //void EraseCheck(); //T GetFirst(); private: std::list< T > m_List; std::list< T >::iterator m_It;//コンパイルエラー }; template <class T> CMyList<T>::CMyList() { m_List.clear(); std::list< T > ::iterator it = m_List.begin();//こう宣言する分にはOK m_It = m_List.begin(); } int main() { CMyList<int> m_List; return 0; }

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

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

  • VC++6.0 インプリメンテーションが見つかりません

    Class Viewからメンバ関数をダブルクリックして定義を探そうとすると、「この関数の定義(インプリメンテーション)が見つかりません」とエラーが出て探せません。 勿論、.cppファイルは存在していますし、FileViewにも出ています。 ビルド・実行は問題なく行えるのですが、編集するのに不便です。 解決する方法は無いでしょうか。

専門家に質問してみよう