合計 昨日 今日

c++のclassについて

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: INER
[URL]
ぴよぴよ(394 ポイント)
Date: 2017年9月05日(火) 02:48
No: 1
(OFFLINE)

 c++のclassについて

最近自作で簡単なゲームを作っているのですが、どうしても自力で解決できない問題にぶち当たってしまいました。ご指導いただけませんか。
問題のコードは↓です。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#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の変数を変更することは可能か。

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

Name: usao
[URL]
ハッカー(136,723 ポイント)
Date: 2017年9月05日(火) 10:01
No: 2
(OFFLINE)

 Re: c++のclassについて

・judge()の引数が値渡しなので,引数をいじくっても意味が無い.
 また,37行目でもわざわざresult_obなるコピー品を生成している.意図が不明.
 簡単に言えば,下記の例で※の箇所でTheIntの値が100にならないのは何故か?と問うていることと等しい.
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
void func( int a ) //値渡し(コピー)
{
  int b = a;  //さらに念入りにコピー
  b = 100;  //コピーのコピーの値を変えました
}
 
int main()
{
  int TheInt = 10;
  func( TheInt );
  //※ここでTheIntの値は何?
}


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

Name: みけCAT
[URL]
伝説なるハッカー(675,355 ポイント)
Date: 2017年9月05日(火) 10:12
No: 3
(OFFLINE)

 Re: c++のclassについて

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

そのとおりですね。
INER さんが書きました:
コード[C++]: 全て選択
1
2
        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の変数を変更することは可能か。

こういうことでしょうか?
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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で殴ればいい!(死亡フラグ)

Name: INER
[URL]
ぴよぴよ(394 ポイント)
Date: 2017年9月05日(火) 15:59
No: 4
(OFFLINE)

 Re: c++のclassについて

[解決!]

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

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


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


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[16人]