std::vectorの使い方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kaiten

std::vectorの使い方

#1

投稿記事 by kaiten » 16年前

テンプレ使わせていただきます。

[1] 質問文
 [1.1] std::vectorを使用してクラスを動的に確保することと、確保したクラスを引数にしないで別のクラスの関数内で使用(うまく言えないのでやりたいコードを書きます。)。
 [1.2] std::vector<Player>
---main.cpp---
#include "class.h"
using namespace std;

char key[256];
int RefreshTime;
int input;
vector<Player> player[1];
BG bg(320, 10, 0);

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lPc, int nC){
	
	ChangeWindowMode(TRUE);

	if(DxLib_Init() == -1)return(-1);
	
	SetDrawScreen(DX_SCREEN_BACK);
	//初期化などの処理を入れる
	SetDrawMode(DX_DRAWMODE_BILINEAR);
	Img_Ini();
	
	while(ProcessMessage() == 0&&GetHitKeyStateAll(key) == 0){
		RefreshTime = GetNowCount();               //今の時間を取得
		ClsDrawScreen();                         //裏画面のデータを全て削除
		
		//実際の処理を入れる(初期化などを除く
		bg.Center();
		player.resize(256);
		ScreenFlip();                             //裏画面データを表画面へ反映
		while(GetNowCount() - RefreshTime < 17);   //1周の処理が17ミリ秒になるまで待つ
		}
	DxLib_End();
	return (0);
}
---class.cpp---
~中略~
void BG::Center()const
	{
	SetDrawArea(x-10, 0, x+10, 480);
	DrawBox(x-10,0,x+10,480,Cr1,TRUE);	
	DrawBox(320-8,480-player.life/player.Get_lifemax()*480,320-2,480,Cr2,TRUE); 
	}
BGクラスの関数内でplayerクラスの関数が使いたいんです。どうにもうまく言えないのですが。

 [1.3] vectorの使い方がいまいちわからない。
1>main.cpp
1>c:\myvc\esth\main.cpp(30) : error C2228: '.resize' の左側はクラス、構造体、共用体でなければなりません
1> 型は 'std::vector<_Ty> [1]' です。
1> with
1> [
1> _Ty=Player
1> ]

 [1.4] vectorを使用すること。また、classを型に指定すること。

[2] 環境  
 [2.1] Windows VISTA
 [2.2] VC++ 2008EE

[3] その他
 C言語、C++ともによくわかってないです。一応龍神録の館を理解するくらいならできるとは思うのですが……
 ライブラリはDxLibを使用しています。

たかぎ

Re:std::vectorの使い方

#2

投稿記事 by たかぎ » 16年前

playerがなぜ配列になっているのか分かりませんが...

player[0].resize(256);

または

player->resize(256);

でよいのでは。

kaiten

Re:std::vectorの使い方

#3

投稿記事 by kaiten » 16年前

>たかぎさん
レスありがとうございます。
main.cppを下記のように変えてみたのですがエラーが出てしまいました。
playerが配列なのは将来的に長さ2の配列で確保するつもりだからです。今はテストも兼ねてリサイズを使ってみているだけでして。

->を使った場合
1>main.cpp
1>c:\myvc\esth\main.cpp(30) : error C2819: クラス 'std::vector<_Ty>' にはオーバーロードされたメンバ 'operator ->' がありません。
1> with
1> [
1> _Ty=Player
1> ]
1> 代わりに '.' を使用しますか?
1>c:\myvc\esth\main.cpp(30) : error C2232: '->std::vector<_Ty>::resize' : 左のオペランドが 'class' 型です。'.' を使用してください。
1> with
1> [
1> _Ty=Player
1> ]
.を使った場合
1>main.cpp
1>c:\program files\microsoft visual studio 9.0\vc\include\vector(713) : error C2512: 'Player::Player' : クラス、構造体、共用体に既定のコンストラクタがありません。
1> c:\program files\microsoft visual studio 9.0\vc\include\vector(712): クラス テンプレート のメンバ関数 'void std::vector<_Ty>::resize(unsigned int)' のコンパイル中
1> with
1> [
1> _Ty=Player
1> ]
1> c:\myvc\esth\main.cpp(10) : コンパイルされたクラスの テンプレート のインスタンス化 'std::vector<_Ty>' の参照を確認してください
1> with
1> [
1> _Ty=Player
1> ]
---main.cpp---
#include "class.h"
using namespace std;

char key[256];
int RefreshTime;
int input;
vector<Player> player;
BG bg(320, 10, 0);

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lPc, int nC){
	
	ChangeWindowMode(TRUE);

	if(DxLib_Init() == -1)return(-1);
	
	SetDrawScreen(DX_SCREEN_BACK);
	//初期化などの処理を入れる
	SetDrawMode(DX_DRAWMODE_BILINEAR);
	Img_Ini();
	
	while(ProcessMessage() == 0&&GetHitKeyStateAll(key) == 0){
		RefreshTime = GetNowCount();               //今の時間を取得
		ClsDrawScreen();                         //裏画面のデータを全て削除
		
		//実際の処理を入れる(初期化などを除く
		bg.Center();
		player->resize(2);
		ScreenFlip();                             //裏画面データを表画面へ反映
		while(GetNowCount() - RefreshTime < 17);   //1周の処理が17ミリ秒になるまで待つ
		}
	DxLib_End();
	return (0);
}
#ちょっと修正しました

たかぎ

Re:std::vectorの使い方

#4

投稿記事 by たかぎ » 16年前

> #ちょっと修正しました

提案したとおりに直すか、自己判断でそれ以上の修正を施すなら適切に調整してください。

kaiten

Re:std::vectorの使い方

#5

投稿記事 by kaiten » 16年前

>修正
これは失礼しました。
vector<Player> player[1];
に戻したところ下記のエラーが発生しました
1>main.cpp
1>c:\program files\microsoft visual studio 9.0\vc\include\vector(713) : error C2512: 'Player::Player' : クラス、構造体、共用体に既定のコンストラクタがありません。
1> c:\program files\microsoft visual studio 9.0\vc\include\vector(712): クラス テンプレート のメンバ関数 'void std::vector<_Ty>::resize(unsigned int)' のコンパイル中
1> with
1> [
1> _Ty=Player
1> ]
1> c:\myvc\esth\main.cpp(10) : コンパイルされたクラスの テンプレート のインスタンス化 'std::vector<_Ty>' の参照を確認してください
1> with
1> [
1> _Ty=Player
1> ]

#以後は記事編集の意だったのですが解りづらかったですね。

たかぎ

Re:std::vectorの使い方

#6

投稿記事 by たかぎ » 16年前

今回のエラーはPlayerクラスの問題です。
まずは、class.hのソースを貼り付けてください。
情報は小出しにせず、回答者側でも現象を再現できるだけの情報を提供してください。

kaiten

Re:std::vectorの使い方

#7

投稿記事 by kaiten » 16年前

失礼しました。
全ファイルそのまま書いておきます
---class.h---
#pragma once
#include "header.h"

extern class Object player1,player2;

class Object
	{
	protected:
		int w,h;
		int lifemax;
		int r;
		int img;
		int speed;
	public:
		float x,y;
		int life;
		int angle;
		Object (){}
		Object(float, float, int, int, int, int, int);
		Object(const Object &copy);
		virtual ~Object();
		void Draw(double)const;
		int Get_lifemax()const;
		int Get_r()const;
		int Get_speed()const;
	};
	
class Player : public Object
	{
	public:
		int player;
		int trigger;
		int score;
		int energy; //専用兵装発射エネルギー。
		Player(int, int, int, int,float, float, int, int, int, int, int);
		Player(const Player &copy, const Object &O_copy);
	};
	
class BG
	{
	protected:
		int w;
		int h;
		int img;
		int Cr1;
		int Cr2;
	public:
		int x;
		int y;
		BG(int, int, int);
		BG(const BG &copy);
		virtual ~BG();
		void Center()const;
	};
---class.cpp---
#pragma once
#include "header.h"

extern class Object player1,player2;
//extern class Player player;

class Object
	{
	protected:
		int w,h;
		int lifemax;
		int r;
		int img;
		int speed;
	public:
		float x,y;
		int life;
		int angle;
		Object (){}
		Object(float, float, int, int, int, int, int);
		Object(const Object &copy);
		virtual ~Object();
		void Draw(double)const;
		int Get_lifemax()const;
		int Get_r()const;
		int Get_speed()const;
	};
	
class Player : public Object
	{
	public:
		int player;
		int trigger;
		int score;
		int energy; //専用兵装発射エネルギー。
		Player(int, int, int, int,float, float, int, int, int, int, int);
		Player(const Player &copy, const Object &O_copy);
	};
	
class BG
	{
	protected:
		int w;
		int h;
		int img;
		int Cr1;
		int Cr2;
	public:
		int x;
		int y;
		BG(int, int, int);
		BG(const BG &copy);
		virtual ~BG();
		void Center()const;
	};
---function.cpp---
#include "class.h"

	
int sin_C(int angle)
	{
	float angle2=(float)angle/10;
	return((int)(sin(angle2)*10));
	}
	
int cos_C(int angle)
	{
	float angle2=(float)angle/10;
	return((int)(cos(angle2)*10));
	}
	
int atan2_C(float y, float x)
	{
	return((int)(atan2((double)y,(double)x)*10));
	}
	
void Img_Ini()
	{
	//Center_Img=LoadGraph();
	Player_Img[0][0]=LoadGraph("Data\\img\\Player\\Nww1P.png");
	Player_Img[1][0]=LoadGraph("Data\\img\\Player\\Nww2P.png");
	}
---header.h---
#pragma once
#define _USE_MATH_DEFINES
#include "DxLib.h"
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <vector>


//define 
#define shiftkeyboard (CheckHitKey(KEY_INPUT_LSHIFT)|CheckHitKey(KEY_INPUT_RSHIFT))
#define shiftPAD	(input&PAD_INPUT_L)
#define up	(input&PAD_INPUT_UP)
#define down	(input&PAD_INPUT_DOWN)
#define left	(input&PAD_INPUT_LEFT)
#define right	(input&PAD_INPUT_RIGHT)
#define PushZ_A	(input&PAD_INPUT_A)
#define PushX_B	(input&PAD_INPUT_B)
#define PushC_C	(input&PAD_INPUT_C)
#define PushA_X	(input&PAD_INPUT_X)
#define PushS_Y	(input&PAD_INPUT_Y)
#define PushD_Z	(input&PAD_INPUT_Z)

#define Bullet_max 3000
#define Effect_max 1000
#define Weapon_max 3
#define Player_kind 3
#define border_x (320-10)
	
//extern
extern int input;
extern int Player_Img[2][Player_kind];

//関数プロトタイプ
int sin_C(int);
int cos_C(int);
int atan2_C(int);
void Img_Ini();
---main.cpp---
#include "class.h"
using namespace std;

char key[256];
int RefreshTime;
int input;
int Player_Img[2][Player_kind];
Object player1(border_x/2, 400, 100, 0, 2, 4, Player_Img[0][0]);
Object player2(border_x/2, 80, 100, 1800, 2, 4, Player_Img[1][0]);
vector<Player> player[1];
BG bg(320, 10, 0);

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lPc, int nC){
	
	ChangeWindowMode(TRUE);

	if(DxLib_Init() == -1)return(-1);
	
	SetDrawScreen(DX_SCREEN_BACK);
	//初期化などの処理を入れる
	SetDrawMode(DX_DRAWMODE_BILINEAR);
	Img_Ini();
	
	while(ProcessMessage() == 0&&GetHitKeyStateAll(key) == 0){
		RefreshTime = GetNowCount();               //今の時間を取得
		ClsDrawScreen();                         //裏画面のデータを全て削除
		
		//実際の処理を入れる(初期化などを除く
		bg.Center();
player->resize(2);
		//player1.Draw(1.0);
		//player2.Draw(1.0);
		//player[0].Draw(1.0);
		ScreenFlip();                             //裏画面データを表画面へ反映
		while(GetNowCount() - RefreshTime < 17);   //1周の処理が17ミリ秒になるまで待つ
		}
	DxLib_End();
	return (0);
}

バグ

Re:std::vectorの使い方

#8

投稿記事 by バグ » 16年前

各クラスのメンバ関数が実装されていないのが原因なのでは?

たかぎ

Re:std::vectorの使い方

#9

投稿記事 by たかぎ » 16年前

デフォルトコンストラクタを定義していないのであれば、適当にコピー元になるオブジェクトを指定する必要があります。
resizeの場合は第二引数を指定してください。

kaiten

Re:std::vectorの使い方

#10

投稿記事 by kaiten » 16年前

player->resize(2);はデフォルトコンストラクタを定義することで解決しました。本当にありがとうございました。

ここからが本題なのですが、
bg.center()からplayer1.Get_life()を呼ぶ方法はあるのでしょうか?それともその必要が出ること自体が失敗なのでしょうか?

たかぎ

Re:std::vectorの使い方

#11

投稿記事 by たかぎ » 16年前

> bg.center()からplayer1.Get_life()を呼ぶ方法はあるのでしょうか?

Get_lifeとは?
PHPとかではないので、存在しないメンバ関数を呼ぶことはできません。

> ここからが本題なのですが、

タイトルの「std::vectorの使い方」とは何の関係もないような...

kaiten

Re:std::vectorの使い方

#12

投稿記事 by kaiten » 16年前

>Get_life
書き間違いでした。正しくはGet_lifemaxです。

>本題
player1のような場合はヘッダでextern宣言すればできると思うのですが、vectorで確保した動的配列でそれができるのか知りたかったんです。解説サイトなどだとvectorで確保してその場で使うような例しか見つからなかったもので……

たかぎ

Re:std::vectorの使い方

#13

投稿記事 by たかぎ » 16年前

> player1のような場合はヘッダでextern宣言すればできると思うのですが、vectorで確保した動的配列でそれができるのか知りたかったんです。

player1.Get_lifemax()を呼び出したいんですよね。
だったらstd::vectorは何の関係もないと思いますが...
bg.center()とした場合に、centerというメンバ関数がないためにエラーになるという話でしょうか?

kaiten

Re:std::vectorの使い方

#14

投稿記事 by kaiten » 16年前

いえ、player1.Get_lifemax()は呼び出せるんです。
vector<Player> playerで確保したplayer[0](と[1])を呼びだしたいんです。

バグ

Re:std::vectorの使い方

#15

投稿記事 by バグ » 16年前

ようするにBGクラスのメンバであるCenter関数で、Playerクラスのメンバを参照したいという事ですよね?
Center関数の引数にPlayerクラスへのポインタを渡してやればいいのではないでしょうか?

たかぎ

Re:std::vectorの使い方

#16

投稿記事 by たかぎ » 16年前

> Center関数の引数にPlayerクラスへのポインタを渡してやればいいのではないでしょうか?

ポインタなり参照なりを渡してもよいですし、そもそもplayerもグローバル変数なので直接触れるはずです。
ただし、player[1]というのは存在しませんのでアクセスできません。

kaiten

Re:std::vectorの使い方

#17

投稿記事 by kaiten » 16年前

うーむ、まずはもう少しC++そのものに慣れて頭を整理してからもう一度挑戦することにします。
ともあれ、本当にありがとうございました。

コウタロウ

通れない場所の作り方について

#18

投稿記事 by コウタロウ » 16年前

以下のような配列で通れない場所を設定しているのですが、
1の所を上下からは通れないのですが、横からは通れてします。
キャラ画像は28×28の画像を用いています。
どなたか原因がわかる方、ご教授願います。
int hantei1_1[13][18] = {
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1 },
        { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1 },
        { 1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1 },
        { 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1 },
        { 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1 },
        { 1,0,1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1 },
        { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 },
        { 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1 },
        { 1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,1 },
        { 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1 },
        { 1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};

int can_or_cannot(int x,int y,int muki){//進めるかを判定する
        if(muki==0)//上向きなら
                if(hantei1_1[y-1][x]==1)//進めるか判定
                        return 1;//進めない
        if(muki==1)//左向きなら
                if(hantei1_1[y][x-1]==1)
                        return 1;
        if(muki==2)//下向きなら
                if(hantei1_1[y+1][x]==1)
                        return 1;
        if(muki==3)//右向きなら
                if(hantei1_1[y][x+1]==1)
                        return 1;
        return 0;//正常
}
			
		if(ch.x%28==0 && ch.y%28==0){         //座標が28で割り切れたら入力可能
            ch.walking_flag=1;         //歩くフラグを立てる。
            if     ( Key[ KEY_INPUT_UP   ]  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
            else if( Key[ KEY_INPUT_RIGHT ]  == 1 )  //右ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( Key[ KEY_INPUT_DOWN ]  == 1 )  //下ボタンが押されたら
                    ch.muki=2;         //下向きフラグを立てる
            else if( Key[ KEY_INPUT_LEFT]  == 1 )  //左ボタンが押されたら
                    ch.muki=3;         //右向きフラグを立てる
            else                                    //何のボタンも押されてなかったら
                    ch.walking_flag=0; //歩かないフラグを立てる
			if(ch.walking_flag==1)    //もし歩くなら
                if(can_or_cannot(ch.x/28,ch.y/28,ch.muki)==1)//行き先が歩けないなら
                    ch.walking_flag=0;                  //歩かないフラグを立てる
        }

        if(ch.walking_flag==1){        //歩くフラグが立っていたら
            if     (ch.muki==0)        //上向きならch.y座標を減らす
                    ch.y--;
            else if(ch.muki==1)        //左向きならch.x座標を減らす
                    ch.x++;
            else if(ch.muki==2)        //下向きならch.y座標を増やす
                    ch.y++;
            else if(ch.muki==3)        //右向きならch.x座標を増やす
                    ch.x--;
        }
 

Dixq (管理人)

Re:通れない場所の作り方について

#19

投稿記事 by Dixq (管理人) » 16年前

キャラの初期座標が28の倍数じゃないんじゃないでしょうか?
後ソースコードを投稿するときはタグを使ってくださいね。
詳しくは規約をご覧ください。

コウタロウ

Re:通れない場所の作り方について

#20

投稿記事 by コウタロウ » 16年前

すいません。以後気をつけます。
キャラの初期座標はちゃんと28の倍数で設定しています。

conio

Re:通れない場所の作り方について

#21

投稿記事 by conio » 16年前

if ( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
ch.muki=0; //上向きフラグを立てる
else if( Key[ KEY_INPUT_RIGHT ] == 1 ) //右ボタンが押されたら
ch.muki=1; //左向きフラグを立てる
else if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
ch.muki=2; //下向きフラグを立てる
else if( Key[ KEY_INPUT_LEFT] == 1 ) //左ボタンが押されたら
ch.muki=3; //右向きフラグを立てる

↑このプログラムは、
------------------------------------------------
下ボタンが押された時 ⇒ 下向きフラグを立てる
上ボタンが押された時 ⇒ 上向きフラグを立てる
右ボタンが押された時 ⇒ 右向きフラグを立てる
左ボタンが押された時 ⇒ 左向きフラグを立てる
------------------------------------------------
という解釈でいいんですよね?

右と左が逆になっているような気がするのですが。
右ボタンが押された時、左向きフラグが立ってますよ。(左ボタンも同様)

コウタロウ

Re:通れない場所の作り方について

#22

投稿記事 by コウタロウ » 16年前

conioさん、ありがとうございます。解決しました。
こんな些細なミスでお恥ずかしいです。

box

Re:通れない場所の作り方について

#23

投稿記事 by box » 16年前

何かの関数のコードに割り込む形で
can_or_cannot関数のコードが入っているように見えるのは
いいのですか?

閉鎖

“C言語何でも質問掲示板” へ戻る