c++のclassについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
INER
記事: 4
登録日時: 8ヶ月前

c++のclassについて

#1

投稿記事 by INER » 8ヶ月前

最近自作で簡単なゲームを作っているのですが、どうしても自力で解決できない問題にぶち当たってしまいました。ご指導いただけませんか。
問題のコードは↓です。

コード:

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <vector>

class test {
private:
	int number;
public:
	void number_reduce(int num);
	int number_give();
	void set(int num);
	int judge(std::vector<test> test_vector);
};

void test::number_reduce(int num) {
	number -= num;
}


int test::number_give(){
	return number;
}

void test::set(int num) {
	number = num;
}

int test::judge(std::vector<test> test_vector) {

	auto result = std::find_if(test_vector.begin(), test_vector.end(), [](test t) {return t.number == 5; });
	
	if (result == test_vector.end()) {
		return 0;
	}else {

		test result_ob = *result;
		result_ob.number_reduce(1);

		printf("私は%d番です\n", number);
		printf("悪いのは%d番です\n", result_ob.number_give());
	}
}

int main(void){

	test ob[10];
	std::vector<test> test_vector(10);

	int i;
	for (i = 0; i <= 9;i++) {
		ob[i].set(i);
		test_vector.push_back(ob[i]);
	};

	for (i = 0; i <= 9; i++) {
		ob[i].judge(test_vector);
	};

	return 0;
}
元々のゲームでは、敵キャラクタのオブジェクト(配列で宣言)をvectorへ収納し条件に合う敵をfind_ifで検索してそのHPを減らす、という目的で↑に似たコードを書いていましたが、そのコードでは一時的に敵HPが変化するだけで元に戻ってしまう(変化もしていない?)現象が発生しました。いろいろと調べる中で↑のコードを書いたところ同様の問題が発生したため、自分がclassとvectorの扱いを間違えていることが分かりました。

【疑問点】
↑のコードではnumber = 5のオブジェクトが発見された際に、そのオブジェクトのnumberを減らす関数を実行しているので最下部のfor の2週目以降は検索してもnumber = 5のオブジェクトは発見されないはずなのですが、結果は↓のようになってしまいます
    結果:私は0番です
       悪いのは4番です
       私は1番です
       悪いのは4番です
       私は2番です
       悪いのは4番です
       私は3番です
       悪いのは4番です
       私は4番です
       悪いのは4番です
       私は5番です
       悪いのは4番です
       私は6番です
       悪いのは4番です
       私は7番です
       悪いのは4番です
       私は8番です
       悪いのは4番です
       私は9番です
       悪いのは4番です

number_reduce関数を使用した直後はnumberが4になっていることが確認できるのですが、それ以降は5に戻り再び1引かれて4になり……ということを繰り返してしまっているように感じます。

色々と調べたのですが、かれこれ1週間以上悩んでいます。
恐らくはコピーと参照の違い等の初歩的な問題だとは思うのですが……ご教授ください。申し訳ないです。

【質問】
2点です。
①なぜnumber = 5を持つオブジェクトのnumberを減らすことができないのか。(なぜnumber = 5へ戻ってしまうのか)
②find_if を使用して発見したオブジェクトのprivateの変数を変更することは可能か。

以上です。よろしくお願いいたします。

アバター
usao
記事: 1375
登録日時: 5年前

Re: c++のclassについて

#2

投稿記事 by usao » 8ヶ月前

・judge()の引数が値渡しなので,引数をいじくっても意味が無い.
 また,37行目でもわざわざresult_obなるコピー品を生成している.意図が不明.
 簡単に言えば,下記の例で※の箇所でTheIntの値が100にならないのは何故か?と問うていることと等しい.

コード:

void func( int a ) //値渡し(コピー)
{
  int b = a;  //さらに念入りにコピー
  b = 100;  //コピーのコピーの値を変えました
}

int main()
{
  int TheInt = 10;
  func( TheInt );
  //※ここでTheIntの値は何?
}
・>②find_if を使用して発見したオブジェクトのprivateの変数を変更することは可能か。
 ここで「変更する」とは「値を減らすこと」を指すのだと想像するが…
 その作業をしたいがためにわざわざ number_reduce() なるメソッドを用意したのではないのか?

アバター
みけCAT
記事: 6012
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: c++のclassについて

#3

投稿記事 by みけCAT » 8ヶ月前

INER さんが書きました:恐らくはコピーと参照の違い等の初歩的な問題だとは思うのですが
そのとおりですね。
INER さんが書きました:

コード:

		test result_ob = *result;
		result_ob.number_reduce(1);
という部分において、vectorに入っているオブジェクトではなくそのコピーのnumber_reduce()を呼び出しており、
このコピーはこのブロックを抜けると破棄されるので、numberを減らした結果は保存されません。
result_obの型をtestからtest& (testへの参照) にすることで、vectorに入っているオブジェクトの操作をresult_obを介してできるでしょう。
さらにこの操作対象のvectorもmain関数からコピーされたものであり、judge関数を抜けると破棄されます。
judge関数の引数も参照にするといいでしょう。
INER さんが書きました:①なぜnumber = 5を持つオブジェクトのnumberを減らすことができないのか。(なぜnumber = 5へ戻ってしまうのか)
numberを減らしたオブジェクトを破棄して別のオブジェクトを見ているため、number = 5に戻ってしまうように見えるだけでしょう。
INER さんが書きました:②find_if を使用して発見したオブジェクトのprivateの変数を変更することは可能か。
こういうことでしょうか?

コード:

#include <cstdio>
#include <vector>
#include <algorithm>

class test {
private:
	int number;
public:
	test() : number(0) {}
	test(int n) : number(n) {}
	int get_number();
	void judge(std::vector<test>& test_vector);
};

int test::get_number(){
	return number;
}

void test::judge(std::vector<test>& test_vector) {
	std::find_if(test_vector.begin(), test_vector.end(),
	[](test& t) {
		if (t.number == 5) {
			t.number--;
			return true;
		} else {
			return false;
		}
	});
}

int main(void){
	test ob;
	std::vector<test> test_vector;
	test_vector.push_back(test(5));
	printf("%d\n", test_vector[0].get_number());
	ob.judge(test_vector);
	printf("%d\n", test_vector[0].get_number());
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

INER
記事: 4
登録日時: 8ヶ月前

Re: c++のclassについて

#4

投稿記事 by INER » 8ヶ月前

usao さん、 回答ありがとうございます。
例が非常にわかりやすかったです。いかに自分がオバカなことをしているかがよくわかりました……。ありがとうございました!

みけCATさん 回答ありがとうございます。
参照させることで元のゲームの方の問題も解決しました。ありがとうございました!


今回の件で基礎の大切さが身に染みて分かりました。復習も重要ですね……。

返信

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