C言語でクラスの中でvectorを使う方法について

このQ&Aのポイント
  • C++の質問です。クラスの中でクラスをベクターで使うことはできますでしょうか?
  • 画像にペイントしたものをラインごとに保存するプログラムを作っています。
  • わからないことは1、ベクターで宣言したクラスの中身を個別にアクセスしたい。たとえば linesのpointにはA lineにはBといようにアクセスしたいです。説明がうまくできませんがアドバイスいただけたら助かります。
回答を見る
  • ベストアンサー

c言語 クラスの中でvectorをクラスに使う

C++の質問です。クラスの中でクラスをベクターで使うことはできますでしょうか? 画像にペイントしたものをラインごとに保存するプログラムを作っています。 わからないことは 1、ベクターで宣言したクラスの中身を個別にアクセスしたい。 たとえば linesのpointにはA lineにはBといようにアクセスしたいです。 説明がうまくできませんがアドバイスいただけたら助かります。 以下がソースになります。 =line.h========================================================= class paintedline{ public: //左上座標 Tvector2<int> point; //上下左右の保存 int top,botton,left,right; //線の格納 vector<Tvector3<int>> line; paintedline(); }; =linegroup.h========================================================= #include "icg.h" #include"line.h" class line_group{ float choosing_line; public: vector<paintedline> lines; line_group(); //線を保存--------------クリックしてから離すまで void saveline(Tvector2<int>point, vector<Tvector3<int>> line); //線を決定--------------クリックして線を決定 int return_line(Tcolor4<float> color); //線を移動 void move_line(Tvector2<int>pa, Tvector2<int>pb); //線を削除 void delete_line(); //すべての線をpaintedに合成 void synthesizing_lines(); }; =linegroup.cpp========================================================= #include"linegroup.h" #include"line.h" line_group::line_group(){ } //線を保存--------------クリックしてから離すまで void line_group::saveline(Tvector2<int>point, vector<Tvector3<int>> line){ //線の四隅を保存 for(int i=0; i<(int)line.size(); i++){ if(top>line.y) top = line.y; if(botton<line.y) botton = line.y; if(left>line.x) left = line.x; if(right<line.x) right = line.x; } //書かれた線を保存 lines.push_back(line) } //線を決定----------------クリックして線を決定 int line_group::return_line(Tcolor4<float> color){ choosing_line = color.r// rに格納したばんごうを決定 return choosing_line } //線を移動 void line_group::move_line(Tvector2<int>pa, Tvector2<int>pb,){ int x = abs(pa.x - pb.x); int y = abs(pa.y - pb.y); lines.at(n).point = (x,y); synthesizing_lines(); } //線を削除 void line_group::delete_line(){ cout<<"deleteするならdを押してください。"<<endl; lines.erace(choosing_line); }

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

  • ベストアンサー
  • hitomura
  • ベストアンサー率48% (325/664)
回答No.4

>// lineは値渡しなので変更しても呼び出し元には影響しない >pl.line.swap(line);とありますが >pl.line = line;ではだめでしょうか?? それでもOKです。速度の問題が無ければ。 swap()はvectorが内部に持っているデータを、引数として渡された別のvectorと交換するメソッドです。 vectorの内部構造についてはさまざまですが、たいていの場合、動的確保されたメモリ領域へのポインタとその領域を管理するのに必要なデータで構成されています。 単なるコピーの場合、(必要なら)現在保持している領域の開放→コピー元と同じ大きさの領域確保→各要素のコピーという処理が行われます。これらはいずれも遅い処理です。 それに対して、swap()の場合、ポインタおよび管理データの交換だけなので上記と比較すると早い処理です。 それゆえ、コピー元を壊してもいいならばswap()のほうがコピー速度は速いです。 #ひょっとしたらとんでもない説明ミスがあるかもしれないので、その場合は訂正お願いします>ほかの回答者様 >またhitomuraさんが1から作ったコードと、改善していただいたコードの違いは速度の問題ですか? 内部処理については以下に書いたとおり速度の問題です。 しかし、追加用のデータ作成処理をpaintedlineクラスに移したのは、そのデータ作成方法はpaintedlineクラスだけが知っていればいいことであるためです。 また、paintedlineクラスの変数に直接アクセスできないようにしたのは、これらを外部から勝手に変更させないためです。 このあたりはオブジェクト指向プログラミングの原則の一つのカプセル化の基礎です。 >:iterator ite = line_.begin();などのあたりはまだ勉強したことがなかったです。 これはイテレーターといって、vectorの要素を指すためのクラスです。vectorの各要素に対するループを回すならばイテレーターを使ったほうが効率的になります。 今回の場合上下左右の初期値を決めるため特殊なことをやっていますが、 vector<Hoge> hoge; // === hogeに要素を追加 === for(vector<Hoge>::iterator ite = hoge.begin();ite != hoge.end(); ite++){ // 各要素に対する処理:要素のデータはポインタと同じように->で取得する } という具合にすれば最初から最後までの要素に対するループを回せます。 STLの効率的な使い方についてはスコット・メイヤーズの『Effective STL』にまとめられていますので、一読されることをお勧めします(参考URL:Amazon.co.jpの同書ページへのリンク)。 ただ、STLの入門書ではないため、STLの基礎についてはほかの本を読んだほうがいいでしょう。

参考URL:
http://www.amazon.co.jp/dp/4894714108/
larry0708
質問者

お礼

遅くなりましたが,詳しい説明ありがとうございました. なんとか目的のものが完成できました.紹介していただいた本も確認してみます.

その他の回答 (3)

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.3

Tvectorとか書いてあるのがよくわかりませんが、std::vectorなら動的なサイズ変更が可能であることを除けば扱い方は普通の配列とほとんど変わりません。 ですからクラス内にvectorを持つことも、クラスをvector化することももちろん普通にできます。 #ただし自作クラスの場合はコピーコンストラクタを書いておいた方が無難。 AとかBとかいう話はもっと具体的に書いてもらわないと何とも言い難いんですが、個別アクセスというのは「vectorの各要素にアクセス」とは何か違うんでしょうか?

larry0708
質問者

お礼

説明が不足していてすみません.なんとか問題が解決できました.

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.2

関数1個しか書かないけど、こんな感じでどうでしょう。 //線を保存--------------クリックしてから離すまで void line_group::saveline(Tvector2<int>point, vector<Tvector3<int>> line){ // lineが空なら何もしない if(line.empty()) return; paintedline pl; //線の四隅を保存 for(int i=0; i<(int)line.size(); i++){ // 最初のループでは四隅の値が不定なので初期化 if(i == 0){ pl.top = pl.bottom = line[i].y; pl.left = pl.right = line[i].x; continue; } if(pl.top>line[i].y) pl.top = line[i].y; if(pl.botton<line[i].y) pl.botton = line[i].y; if(pl.left>line[i].x) pl.left = line[i].x; if(pl.right<line[i].x) pl.right = line[i].x; } pl.point = point; // lineは値渡しなので変更しても呼び出し元には影響しない pl.line.swap(line); //書かれた線を保存 lines.push_back(pl) } ……ただし、自分ならばこうします。 =line.h= #ifndef(LINE_H) #define LINE_H class paintedline{ private: //左上座標 Tvector2<int> point_; //上下左右の保存 int top_,botton_,left_,right_; //線の格納 vector<Tvector3<int>> line_; public: paintedline(const Tvector2<int>& point, const vector<Tvector3<int>>& line); // コピーコンストラクタと代入演算子は(多分必要だが文字数制限で入らないので)省略 //左上座標 const Tvector2<int>& get_point() const {return point_;}; //上下左右 int get_top() const {return top_;}; int get_bottom() const {return botton_;}; int get_left() const {return left_;}; int get_right() const {return right_;}; //線 const vector<Tvector3<int>>& get_line() const {return line_;}; } #endif//LINE_H =line.cpp= #include"line.h" paintedline::paintedline(const Tvector2<int>& point, const vector<Tvector3<int>>& line) :point_(point), line_(line) { if(line.empty()){ top_ = botton_ = left_ = right_ = 0; return; } top_ = bottom_ = line.begin()->y; left_ = right_ = line.begin()->x; vector<Tvector3<int>>::iterator ite = line_.begin(); ite++; for(;ite != line_.end(); ite++){ if(top_>ite->y) top_ = ite->y; if(botton_<ite->y) botton_ = ite->y; if(left_>ite->x) left_ = ite->x; if(right_<ite->x) right_ = ite->x; } }; =linegroup.cpp= //線を保存--------------クリックしてから離すまで void line_group::saveline(const Tvector2<int>& point, const vector<Tvector3<int>>& line){ lines.push_back(paintedline(point, line); }

larry0708
質問者

お礼

私の不十分な説明と、下手なコードで理解していただけたようでとても感謝しています。 // lineは値渡しなので変更しても呼び出し元には影響しない pl.line.swap(line);とありますが pl.line = line;ではだめでしょうか?? またhitomuraさんが1から作ったコードと、改善していただいたコードの違いは速度の問題ですか?:iterator ite = line_.begin();などのあたりはまだ勉強したことがなかったです。 分かりやすい説明で助かります。ありがとうございます。

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

「クラスの中でクラスをベクターで使うこと」はできて当然. vector のインターフェイスはそんなに変態ちっくなものじゃないので, ここで使うくらいなら「こんな感じかな」と単純に考えればだいたいできるはず. でこのプログラムが何をしたいのかさっぱりわからんのだけど, 少なくとも void line_group::saveline(Tvector2<int>point, vector<Tvector3<int>> line) の中身が*あまりにもおかしい*ことはわかる. むしろ「line.x」などと書けると考えた理由を知りたい.

larry0708
質問者

お礼

自分自身理解していないため、質問が不明確になってすみません。 Tvector3は自分で作った3つの変数を持つ構造体です。 line.xで変数をとりだしています。 上手く伝えられるように、理解できるように自分自身もっと勉強をします。

関連するQ&A

  • C言語ベクトルの内積計算について

    以下に示すベクトルx,yの内積を算出するプログラムを作成してください。ベクトルは配列として扱い、変数はすべてint型を用いて下さい。また、内積の算出には、void型関数を使用し、算出結果はコマンドライン上に出力すること。 x=(1,2,3),y=(5,6,7)

  • コンパイルすると error C1083 が出てしまいます

     -スペック- Microsoft Visual Studio 2008 Version 9.0.21022.8 RTM Microsoft .NET Framework Version 3.5 SP1 ---------------------------------------------------------------- 以下のプログラムを実行すると、error C1083: include ファイルを開けません。'myhelper.h': No such file or directory っていうエラーが出ます。 ----------------------------------------------------------------  -プログラム-  - mymain.cpp の中身 - #include "myhelper.h" #include "mymain.h" //自キャラのデータ Point2D g_jikipos = {40, 400}; //自キャラの座標 //画像ハンドル int g_jikiimage[11]; //色々なファイルの読み込み int LoadFiles(){ //画像ファイル読み込み if(LoadDivGraph("media\\player01.bmp", 11,11,1,64,64,g_jikiimage) == -1) return -1; return 1; }  - mymain.h の中身 - //他から呼び出させるMyMainの関数 void MyMain(); int LoadFiles();  - myhelper.h の中身 - #include "DxLib.h" #include <limits.h> #include <math.h> //構造体宣言 //座標またはベクトルを記録する構造体 struct Vector{ float x,y; }; typedef Vector Point2D; //線を記録する構造体 struct Line2D{ Point2D startpos, endpos; float katamuki; //傾きをラジアン値で記録 Vector speed; //移動している場合は速度をセット }; //球体を記録する構造体 struct Ball2D{ Point2D position; float hankei; //半径 }; //四角形を記録する構造体 struct Rect2D{ Point2D lefttop; Point2D rightbottom; float width; float height; }; //ライブラリ関数 Point2D PosInView(Point2D in); int XInView(float inx); int YInView(float iny); void ScrollToLeft(float jikiposx); void ScrollToRight(float jikiposx); void ScrollToUp(float jikiposy); void ScrollToDown(float jikiposy); void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness); void DrawCircleInView(float x, float y, float r, int Color, int FillFlag); void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag, int *imgarray, int allframe, float fps); //ベクトル関数 Vector CreateVector(Vector in, float veclen); Vector AddVector(Vector v1, Vector v2); Vector SubVector(Vector v1, Vector v2); Vector AddVectorInFrameTime(Vector pos, Vector speed); Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel); Vector Normalize(Vector in); Vector RotateVector(Vector in, float radian); float VectorLengthSquare(Vector in); float DotProduct(Vector v1, Vector v2); float CrossProduct(Vector v1, Vector v2); void SetLine2DKatamuki(Line2D *in); void DrawLine2D(Line2D in, int Color, int Thickness); void DrawBall2D(Ball2D in, int Color, int Fill); //当たり判定関数 bool HitTestLineAndBall(Line2D linein, Ball2D ballin); bool IsPointAtLineFace(Line2D linein, Point2D ptin); bool HitTestLineAndLine(Line2D line1, Line2D line2); bool HitTestBallAndBall(Ball2D a, Ball2D b); bool HitTestPointAndBox(Rect2D rect, Point2D pt); //タイマー関数 void SetSimpleTimer(int idx, int time); int GetPassedTime(int idx); //グローバル変数 extern float g_frametime; extern Rect2D g_framerect; //画面領域(当たり判定) extern Point2D g_current_field_pos; //現在の左上座標 extern Rect2D g_stagesize; //ステージサイズ //定数宣言 const float ZEROVALUE = 1e-10f; const float PIE = 3.1415926f; const int SCROLL_LIMIT = 200; myhelper.h はコピペなので間違ってはない。 ---------------------------------------------------------------- まだC言語初心者なので、どのようにすれば直せるのかわからないので 詳しくお願いします。 一応サイトで検索などをして、自分なりに調べてきて 定義が間違ってないかを見ましたけどそれでもまだわかりません。 それでは宜しくお願いします。

  • 【C++】関数からクラスに変更するには?

    いつも大変お世話になっています。 VC++初心者です。 関数をクラス化していきたいのですが、具体的にどのようにしたら良いか ご指導頂けませんでしょうか。 例えば、このようなソースがあった場合、どのようにクラス化させるのでしょうか。 (また、下記の例ですと、pulsとsubで1つのグループ、 goodMoringとgoodNightで1つのグループにさせる場合には どうすれば宜しいでしょうか。) //======================= //Tool.hの中身 //======================= int plus(int x, int y); int sub(int x, int y); void goodMorning(); void goodNight(); //======================= //Tool.cppの中身 //======================= #include <iostream.h> int plus(int x, int y){ return x + y; } int sub(int x, int y){ return x - y; } void goodMorning(){ cout << "おはよう\n"; } void goodNight(){ cout << "こんばんは\n"; } //======================= //Main.cppの中身 //======================= #include <iostream.h> #include "Tool.h" int main(){ int a = puls(1,1); cout << a <<'\n'; int b = puls(2,1); cout << b <<'\n'; goodMorning(); goodNight(); }

  • クラスメソッドのみのクラスのオブジェクト生成は不可??

    あるテキストのjavaの問題です。 public class Draw{   static void pixel(int x,int y){     /*座標(x、y)に点を描画*/   }   static void line(int x1,int y1,int x2,int y2){     /*座標(x1、y1)~(x2、y2)に線を引く*/   } } で、これを実行するための以下のようなクラス public class TestDraw{ <ここに入力> } という問題なのですが2つまでは絞れたのですが、 (1) public static void main(String args[]){   Draw d = new Draw().line(10,10,20,30); } ↑× (2) public static void main(String args[]){   Draw.line(10,10,20,30); } ↑○ (2)はlineメソッドがstaticメソッドだからオブジェクト生成しなくても良い、ということなんですが (1)も正解のような気がするのですが・・・ 解説によると「lineはvoidなのでnew Draw().line(10,10,20,30);とすれば正解、とあります。 どうもいまいち理解できません。 クラスメソッドはオブジェクト生成しなくとも良い→オブジェクト生成できない ということなのでしょうか? それからちなみに、public classって2つ記述できないんではありませんでしたか?

    • ベストアンサー
    • Java
  • c言語

    #include<stdio.h> main(void) { int x; double y,sum; void p(double *); for(sum=0.0,x=1;x<10;x++){ sum+=1.0/p(&x); ここでエラーがでます。 } printf("%d\n",sum); } void p(double *y) { *y*=*y; } どうしてエラーがでるかわかりません。教えてください!

  • C言語なうなんですが、コンパイルまでは行ったんですが、セグメントエラー

    C言語なうなんですが、コンパイルまでは行ったんですが、セグメントエラーを起こしてしまいます。初心者なのでどこがおかしいのかもわかりませんので、ご指摘いただけるとありがたいです。 以下がそれでゲソ。始点と終点を指定して線を描いてもらうプログラミングを目指す。 #include <stdio.h> #include "../Glib/Glib.h" int main(void) { int x1,y1,x2,y2; printf("直線の始点の座標(x1,y1)のx1,y1を、間にカンマ','を入れて入力してください。"); scanf("%d" ,"%d" ,&x1 ,&y1); printf("直線の終点の座標(x2,y2)のx1,y1を、間にカンマ','を入れて入力してください。"); scanf("%d" ,"%d" ,&x2 ,&y2); G_init(); G_open(800,600,"Draw Line"); G_show(); G_black(); G_fillrect(0, 0, 800, 600); G_flush(); printf("Return Key を押してください。\n"); getchar(); G_white(); G_fillrect(0, 0, 800, 600); G_rgb(0,0,8); void G_line(int x1, int y1, int x2, int y2); G_flush(); printf("Return key を何回か押すと終了します。\n"); getchar(); getchar(); G_close(); return (0); }

  • C言語のポインタの考え方について

    ポインタについて理解ができていないのでお聞きしたいのですが 値を交換する関数のプログラミングでこの場合ポインタ で以下にしないといけないと思います。 #include<stdio.h> void swap(int *a int *b){ int c; c=*a; *a=*b; *b=c; } main(){ int x,y; x=123; y=456; swap(&x,&y); printf("x = %d, y = %d\n", x, y); } またポインタを使用せず以下のプログラムではなぜダメのでしょうか。 よろしくお願い致します。 #include<stdio.h> void swap(int a int b){ int c; c=a; a=b; b=c; } main(){ int x,y; x=123; y=456; swap(x,y); printf("x = %d, y = %d\n", x, y); }

  • C言語のプログラムについてです。

    円を描くプログラムを作りたいのですが、条件としてpointを使わないでつくらなければなりません。あとそのプログラムについての説明もいるので、合わせて回答お願いします。pointを使うと↓のプログラムです。 #include<stdio.h> #include<math.h> int main(void); int main(void) { double point[2][2]; double r; double pi=3.14159; int i; onenpl(); space(-100.0,-100.0,100.0,100.0); printf("円を描きます\n"); printf("半径を入力してください\n"); scanf("%lf",&r); point[0][0]=r*cos(0.0); point[0][1]=r*sin(0.0); for (i=1;i<360;i=i+1) { point[1][0]=r*cos(pi/180.0*i); point[1][1]=r*sin(pi/180.0*i); line(point[0][0],point[0][1],point[1][0],point[1][1]); point[0][0]=point[1][0]; point[0][1]=point[1][1]; } closepl(); return(0); }

  • Cのローカル変数でstatic以外の使い方?

    C言語の課題について教えてください [課題] 以下の関数がある。各関数の引数、変数は自由に設定していい ・int main() ・void func() ・Point *get() { /* 構造体のアドレスを返す */ } ・構造体 typedef struct { int x; int y; int h; int w; }Point; 問題 main関数から、func関数を経由して、get関数を経由し値を取得し、表示する 以下が考えたソースになりますが、これだと、 ローカル変数でstaticを使っているので、get関数が固定値ではなく、 取得のたびに値が変わるような場合には、だめだといわれました。 考えたのですがよくわからないので、どういう場合に駄目なのかと、 どのように修正すればいいのか教えてください。 #include <stdio.h> typedef struct { int x; int y; int h; int w; }Point; void func(Point **); Point *get(); int main(void){ Point *get; func(&get); printf("get.x:[%d]\n",get->x); printf("get.y:[%d]\n",get->y); printf("get.h:[%d]\n",get->h); printf("get.w:[%d]\n",get->w); return 0; } void func(Point **pw){ *pw = get(); printf("Wrapper: pw==%p\n",pw); } Point *get(void) { static Point pget; pget.x = 2; pget.y = 2; pget.h = 30; pget.w = 40; return &pget; }

  • C++のことで・・教えてください。

    下記のプログラムはコンパイルはできますが、実行するとエラーとなり強制終了させられてしまいます。いつたいなぜなのでしょうか? #include<iostream.h> struct point{ int x; int y; }; struct pairpoint{ point so; point si; }; pairpoint* h = (pairpoint*)malloc(1); int main(){ h[0].so.x = 1;h[0].so.y = 3; h[0].si.x = 5;h[0].si.y = 7; cout << h[0].so.x << "," << h[0].so.y << endl; cout << h[0].si.x << "," << h[0].si.y << endl; }

専門家に質問してみよう