C++入門|3章の練習問題

3章の仕上げは、修行アイテムと戦士登録で実戦確認。privateで大切なデータを守り、セッターとゲッターで安全に扱おう。

3章では、C++のオブジェクト指向について、クラス、インスタンス、メンバ変数、メンバ関数、public、private、カプセル化、セッター、ゲッター、複数インスタンスについて学んできました。

ここまでの内容は、C++で大きなプログラムを作るための大切な基礎です。

クラスは、オブジェクトを作るための設計図です。
インスタンスは、その設計図から作られた実体です。
メンバ変数は、インスタンスが持つデータです。
メンバ関数は、インスタンスが行う処理です。

ドラゴンボール風にたとえるなら、クラスは修行アイテムや戦士を作る設計図です。
インスタンスは、実際に使われる仙豆カプセル修行戦士です。
メンバ変数は、アイテム名、必要ゼニー、強化倍率、戦士名、流派、戦闘力のようなデータです。
メンバ関数は、情報を表示する、値を設定する、値を取得する、といった動作です。

今回の練習問題では、次の3つを確認します。

練習問題内容確認するポイント
問題3-1修行アイテム情報をカプセル化するprivate、セッター、ゲッター、配列
問題3-21人の修行戦士を登録するカプセル化、入力、showInformation
問題3-32人の修行戦士を登録する複数インスタンス、配列、for文

どの問題でも大切なのは、メンバ変数を直接publicにしないことです。

メンバ変数はprivateにして、外から直接変更できないようにします。
そして、値を設定するときはセッター、値を取得するときはゲッターを使います。

ドラゴンボール風に言えば、戦士の戦闘力や修行アイテムの内部情報を、外から勝手に書き換えられないように、修行カプセルの中に守っておくイメージです。

図:3章の練習問題で確認するカプセル化の流れ

この図が示していること

この図では、3章の練習問題で確認するカプセル化の流れを表しています。

CapsuleItemクラスでは、修行アイテムの情報をprivateで守ります。
KiTraineeクラスでは、修行戦士の情報をprivateで守ります。

main.cppからは、privateなメンバ変数へ直接アクセスせず、publicなセッターとゲッターを使って値を設定・取得します。
最後にshowInformation関数で、クラス内部の情報をまとめて表示します。

問題3-1:修行アイテム情報をカプセル化する

問題文

以下の仕様の、修行アイテム情報を表すCapsuleItemクラスを作りなさい。

このクラスでは、修行アイテム名、必要ゼニー、強化補正率を管理します。
必要ゼニーに強化補正率を加えた「強化後ゼニー」を計算し、アイテム情報として表示してください。

メンバ変数はすべてprivateにし、先頭にm_を付けます。
また、各メンバ変数に対して、セッターとゲッターを追加してください。

メンバ変数

変数名概要
stringm_name修行アイテム名仙豆カプセル
intm_zenny必要ゼニー100
doublem_upgradeRate強化補正率0.1

メンバ関数

戻り値の型関数名引数概要
voidsetNamestring name修行アイテム名を設定する
stringgetNameなし修行アイテム名を取得する
voidsetZennyint zenny必要ゼニーを設定する
intgetZennyなし必要ゼニーを取得する
voidsetUpgradeRatedouble upgradeRate強化補正率を設定する
doublegetUpgradeRateなし強化補正率を取得する
voidshowInformationなしアイテム名、必要ゼニー、強化後ゼニーを表示する

main.cppでは、CapsuleItemクラスの配列を3つ作り、次の修行アイテム情報を設定してください。

アイテム名必要ゼニー強化補正率
仙豆カプセル1000.1
重力ブーツ5000.1
スカウター修理キット1000.08

showInformation関数を使って、3つの修行アイテム情報を表示してください。

期待される実行結果

アイテム名:仙豆カプセル 必要ゼニー:100Z 強化後ゼニー:110Z
アイテム名:重力ブーツ 必要ゼニー:500Z 強化後ゼニー:550Z
アイテム名:スカウター修理キット 必要ゼニー:100Z 強化後ゼニー:108Z

プログラムを作成するヒント

まず、CapsuleItemクラスを作ります。

修行アイテム名、必要ゼニー、強化補正率は、外から直接変更できないようにprivateにします。

private:
    string m_name;
    int m_zenny;
    double m_upgradeRate;

外から値を設定するには、セッターを使います。

void setName(string name);
void setZenny(int zenny);
void setUpgradeRate(double upgradeRate);

外から値を取得するには、ゲッターを使います。

string getName();
int getZenny();
double getUpgradeRate();

showInformation関数では、強化後ゼニーを計算します。

int upgradedZenny = m_zenny + (int)(m_zenny * m_upgradeRate);

main.cppでは、CapsuleItem型の配列を作ります。

CapsuleItem item[3];

そのあと、セッターを使って3つのアイテム情報を設定します。

item[0].setName("仙豆カプセル");
item[0].setZenny(100);
item[0].setUpgradeRate(0.1);

表示するときは、for文でshowInformationを呼び出します。

for (int i = 0; i < 3; i++) {
    item[i].showInformation();
}

図:CapsuleItemクラスで修行アイテムをカプセル化する

この図が示していること

この図では、CapsuleItemクラスのメンバ変数をprivateで守り、publicなセッターとゲッターで扱う流れを表しています。

m_name、m_zenny、m_upgradeRateは直接外から触れません。
main.cppからはsetName、setZenny、setUpgradeRateを使って値を設定します。
表示するときはshowInformationを呼び出し、クラス内部で強化後ゼニーを計算します。

プログラムの解答例

プロジェクト名/ファイル名: Prac3_1/capsule_item.h

#ifndef _CAPSULE_ITEM_H_
#define _CAPSULE_ITEM_H_

#include <iostream>
#include <string>

using namespace std;

// 修行アイテムクラス
class CapsuleItem {
private:
    // 修行アイテム名
    string m_name;

    // 必要ゼニー
    int m_zenny;

    // 強化補正率
    double m_upgradeRate;

public:
    // 修行アイテム名のセッター
    void setName(string name);

    // 修行アイテム名のゲッター
    string getName();

    // 必要ゼニーのセッター
    void setZenny(int zenny);

    // 必要ゼニーのゲッター
    int getZenny();

    // 強化補正率のセッター
    void setUpgradeRate(double upgradeRate);

    // 強化補正率のゲッター
    double getUpgradeRate();

    // 修行アイテム情報を表示する
    void showInformation();
};

#endif // _CAPSULE_ITEM_H_

プロジェクト名/ファイル名: Prac3_1/capsule_item.cpp

#include "capsule_item.h"

// 修行アイテム名を設定する
void CapsuleItem::setName(string name) {
    m_name = name;
}

// 修行アイテム名を取得する
string CapsuleItem::getName() {
    return m_name;
}

// 必要ゼニーを設定する
void CapsuleItem::setZenny(int zenny) {
    m_zenny = zenny;
}

// 必要ゼニーを取得する
int CapsuleItem::getZenny() {
    return m_zenny;
}

// 強化補正率を設定する
void CapsuleItem::setUpgradeRate(double upgradeRate) {
    m_upgradeRate = upgradeRate;
}

// 強化補正率を取得する
double CapsuleItem::getUpgradeRate() {
    return m_upgradeRate;
}

// 修行アイテム情報を表示する
void CapsuleItem::showInformation() {
    // 強化後ゼニーを計算する
    int upgradedZenny = m_zenny + (int)(m_zenny * m_upgradeRate);

    // 修行アイテム情報を表示する
    cout << "アイテム名:" << m_name
         << " 必要ゼニー:" << m_zenny << "Z"
         << " 強化後ゼニー:" << upgradedZenny << "Z"
         << endl;
}

プロジェクト名/ファイル名: Prac3_1/main.cpp

#include "capsule_item.h"

int main(int argc, char** argv) {
    // 修行アイテムのインスタンスを3つ生成する
    CapsuleItem item[3];

    // 仙豆カプセルの情報を設定する
    item[0].setName("仙豆カプセル");
    item[0].setZenny(100);
    item[0].setUpgradeRate(0.1);

    // 重力ブーツの情報を設定する
    item[1].setName("重力ブーツ");
    item[1].setZenny(500);
    item[1].setUpgradeRate(0.1);

    // スカウター修理キットの情報を設定する
    item[2].setName("スカウター修理キット");
    item[2].setZenny(100);
    item[2].setUpgradeRate(0.08);

    // 修行アイテム情報を表示する
    for (int i = 0; i < 3; i++) {
        item[i].showInformation();
    }

    // プログラムが正常に終わったことを示す
    return 0;
}

解説

この問題では、CapsuleItemクラスを使って、修行アイテムの情報を管理しています。

ポイントは、メンバ変数をprivateにしていることです。

private:
    string m_name;
    int m_zenny;
    double m_upgradeRate;

この3つは、クラスの外側から直接アクセスできません。

そのため、main.cppから次のように書くことはできません。

item[0].m_zenny = 100;

これは、m_zennyがprivateだからです。

代わりに、publicなセッターを使います。

item[0].setZenny(100);

この呼び出しによって、setZenny関数の中でm_zennyに値が入ります。

void CapsuleItem::setZenny(int zenny) {
    m_zenny = zenny;
}

値を取得するときは、ゲッターを使います。

int CapsuleItem::getZenny() {
    return m_zenny;
}

このように、privateなメンバ変数を直接触らせず、関数を通して扱うのがカプセル化です。

showInformation関数では、クラス内部のm_name、m_zenny、m_upgradeRateをそのまま使っています。

int upgradedZenny = m_zenny + (int)(m_zenny * m_upgradeRate);

ここでは、必要ゼニーに強化補正分を加えて、強化後ゼニーを計算しています。

たとえば、m_zennyが100、m_upgradeRateが0.1なら、次のようになります。

100 + 100 × 0.1 = 110

main.cppでは、CapsuleItemの配列を作っています。

CapsuleItem item[3];

これにより、item[0]、item[1]、item[2]という3つのインスタンスが生成されます。

配列要素アイテム
item[0]仙豆カプセル
item[1]重力ブーツ
item[2]スカウター修理キット

同じCapsuleItemクラスから作られていますが、それぞれ別々のm_name、m_zenny、m_upgradeRateを持っています。

そのため、3つのアイテム情報を同じクラスで管理できます。

問題3-2:1人の修行戦士を登録する

問題文

以下の仕様の、修行戦士情報を表すKiTraineeクラスを作りなさい。

キーボードから戦士名、年齢、流派、戦闘力を入力し、その修行戦士の情報を表示するプログラムを作りなさい。

なお、メンバ変数はカプセル化し、privateにします。
各メンバ変数には、セッターとゲッターを追加してください。

さらに、セッターとゲッター以外に、修行戦士の情報を1行で表示するshowInformation関数を追加してください。

メンバ変数

変数名概要
stringm_name戦士名Leo
intm_age年齢14
stringm_style流派亀仙流
intm_power戦闘力1200

メンバ関数

戻り値の型関数名引数概要
voidsetNamestring name戦士名を設定する
stringgetNameなし戦士名を取得する
voidsetAgeint age年齢を設定する
intgetAgeなし年齢を取得する
voidsetStylestring style流派を設定する
stringgetStyleなし流派を取得する
voidsetPowerint power戦闘力を設定する
intgetPowerなし戦闘力を取得する
voidshowInformationなし戦士名、流派、年齢、戦闘力を1行で表示する

プログラムを実行すると、次の順番で入力を行います。

戦士名:
年齢:
流派:
戦闘力:

入力後、ゲッターで取得した値を表示し、最後にshowInformation関数を使って、修行戦士の情報を1行で表示してください。

期待される実行結果

戦士名:Leo
年齢:14
流派:亀仙流
戦闘力:1200

------ 入力情報の確認 ------
戦士名:Leo
年齢:14
流派:亀仙流
戦闘力:1200

Leo:亀仙流 14歳 戦闘力1200

プログラムを作成するヒント

KiTraineeクラスでは、戦士名、年齢、流派、戦闘力をprivateなメンバ変数として持たせます。

private:
    string m_name;
    int m_age;
    string m_style;
    int m_power;

それぞれにセッターとゲッターを用意します。

void setName(string name);
string getName();

showInformation関数では、クラス内部のm_name、m_style、m_age、m_powerを使って、1行で情報を表示します。

main.cppでは、入力した値をいったんローカル変数に保存し、セッターでKiTraineeインスタンスに設定します。

trainee.setName(name);
trainee.setAge(age);
trainee.setStyle(style);
trainee.setPower(power);

確認表示では、ゲッターを使います。

cout << "戦士名:" << trainee.getName() << endl;

プログラムの解答例

プロジェクト名/ファイル名: Prac3_2/ki_trainee.h

#ifndef _KI_TRAINEE_H_
#define _KI_TRAINEE_H_

#include <iostream>
#include <string>

using namespace std;

// 修行戦士クラス
class KiTrainee {
private:
    // 戦士名
    string m_name;

    // 年齢
    int m_age;

    // 流派
    string m_style;

    // 戦闘力
    int m_power;

public:
    // 戦士名のセッター
    void setName(string name);

    // 戦士名のゲッター
    string getName();

    // 年齢のセッター
    void setAge(int age);

    // 年齢のゲッター
    int getAge();

    // 流派のセッター
    void setStyle(string style);

    // 流派のゲッター
    string getStyle();

    // 戦闘力のセッター
    void setPower(int power);

    // 戦闘力のゲッター
    int getPower();

    // 修行戦士の情報を表示する
    void showInformation();
};

#endif // _KI_TRAINEE_H_

プロジェクト名/ファイル名: Prac3_2/ki_trainee.cpp

#include "ki_trainee.h"

// 戦士名を設定する
void KiTrainee::setName(string name) {
    m_name = name;
}

// 戦士名を取得する
string KiTrainee::getName() {
    return m_name;
}

// 年齢を設定する
void KiTrainee::setAge(int age) {
    m_age = age;
}

// 年齢を取得する
int KiTrainee::getAge() {
    return m_age;
}

// 流派を設定する
void KiTrainee::setStyle(string style) {
    m_style = style;
}

// 流派を取得する
string KiTrainee::getStyle() {
    return m_style;
}

// 戦闘力を設定する
void KiTrainee::setPower(int power) {
    m_power = power;
}

// 戦闘力を取得する
int KiTrainee::getPower() {
    return m_power;
}

// 修行戦士の情報を表示する
void KiTrainee::showInformation() {
    cout << m_name << ":" << m_style << " "
         << m_age << "歳 戦闘力" << m_power << endl;
}

プロジェクト名/ファイル名: Prac3_2/main.cpp

#include <iostream>
#include <string>
#include "ki_trainee.h"

using namespace std;

int main(int argc, char** argv) {
    // 修行戦士のインスタンスを生成する
    KiTrainee trainee;

    // 入力用のローカル変数を宣言する
    string name;
    string style;
    int age;
    int power;

    // 戦士名を入力する
    cout << "戦士名:";
    cin >> name;

    // 年齢を入力する
    cout << "年齢:";
    cin >> age;

    // 流派を入力する
    cout << "流派:";
    cin >> style;

    // 戦闘力を入力する
    cout << "戦闘力:";
    cin >> power;

    // セッターを使ってインスタンスに値を設定する
    trainee.setName(name);
    trainee.setAge(age);
    trainee.setStyle(style);
    trainee.setPower(power);

    // ゲッターを使って入力情報を確認する
    cout << endl;
    cout << "------ 入力情報の確認 ------" << endl;
    cout << "戦士名:" << trainee.getName() << endl;
    cout << "年齢:" << trainee.getAge() << endl;
    cout << "流派:" << trainee.getStyle() << endl;
    cout << "戦闘力:" << trainee.getPower() << endl;

    // showInformation関数を使って修行戦士の情報を表示する
    cout << endl;
    trainee.showInformation();

    // プログラムが正常に終わったことを示す
    return 0;
}

解説

この問題では、KiTraineeクラスを使って、1人の修行戦士の情報を管理しています。

まず、ki_trainee.hでクラスの宣言を行っています。

class KiTrainee {

このKiTraineeクラスが、修行戦士を表す設計図です。

メンバ変数はprivateにしています。

private:
    string m_name;
    int m_age;
    string m_style;
    int m_power;

privateにすることで、main.cppから直接アクセスできなくなります。

たとえば、次のような書き方はできません。

trainee.m_power = 1200;

外から直接変更させず、セッターを通して値を設定します。

trainee.setPower(power);

setPower関数の中では、引数powerの値をm_powerに代入しています。

void KiTrainee::setPower(int power) {
    m_power = power;
}

値を取得するときは、getPowerを使います。

int KiTrainee::getPower() {
    return m_power;
}

main.cppでは、最初にKiTraineeクラスのインスタンスを生成しています。

KiTrainee trainee;

このtraineeが、実際に使う修行戦士オブジェクトです。

入力した値は、いったんローカル変数に入れます。

cin >> name;
cin >> age;
cin >> style;
cin >> power;

そのあと、セッターを使ってtraineeに値を設定します。

trainee.setName(name);
trainee.setAge(age);
trainee.setStyle(style);
trainee.setPower(power);

入力情報の確認では、ゲッターを使います。

cout << "戦士名:" << trainee.getName() << endl;
cout << "年齢:" << trainee.getAge() << endl;
cout << "流派:" << trainee.getStyle() << endl;
cout << "戦闘力:" << trainee.getPower() << endl;

最後に、showInformationを呼び出しています。

trainee.showInformation();

showInformationの中では、クラス内部のm_name、m_style、m_age、m_powerをそのまま使えます。

クラスの外からはprivateなメンバ変数に直接アクセスできませんが、同じクラスのメンバ関数の中ではそのまま使えます。

図:KiTraineeインスタンスに値を設定して情報を表示する

この図が示していること

この図では、main.cppからKiTraineeインスタンスへ値を設定し、showInformationで情報を表示する流れを表しています。

main.cppは、m_nameやm_powerへ直接アクセスしません。
setNameやsetPowerなどのセッターを使って、値を設定します。

showInformationの中では、privateなメンバ変数を使って、修行戦士の情報を1行で表示します。

問題3-3:2人の修行戦士を登録する

問題文

問題3-2のKiTraineeクラスを使って、2人の修行戦士を登録できるプログラムを作りなさい。

KiTraineeクラスのインスタンスを配列で2つ作り、for文を使って、2人分の戦士名、年齢、流派、戦闘力を入力してください。

入力後、2人分の情報をゲッターで確認し、最後にshowInformation関数で2人の修行戦士情報を表示してください。

期待される実行結果

--- 戦士1の情報を入力 ---
戦士名:Leo
年齢:14
流派:亀仙流
戦闘力:1200

--- 戦士2の情報を入力 ---
戦士名:Noa
年齢:15
流派:神流
戦闘力:1800

--- 戦士1の情報の確認 ---
戦士名:Leo
年齢:14
流派:亀仙流
戦闘力:1200

--- 戦士2の情報の確認 ---
戦士名:Noa
年齢:15
流派:神流
戦闘力:1800

Leo:亀仙流 14歳 戦闘力1200
Noa:神流 15歳 戦闘力1800

プログラムを作成するヒント

2人分のインスタンスを作るには、配列を使います。

KiTrainee trainee[2];

これにより、trainee[0]とtrainee[1]という2つのKiTraineeインスタンスが作られます。

入力処理はfor文で繰り返します。

for (int i = 0; i < 2; i++) {
    // i番目の戦士情報を入力する
}

iが0のときはtrainee[0]、iが1のときはtrainee[1]を扱います。

セッターを使うときも、trainee[i]に対して呼び出します。

trainee[i].setName(name);
trainee[i].setAge(age);
trainee[i].setStyle(style);
trainee[i].setPower(power);

情報を確認するときはゲッターを使います。

cout << "戦士名:" << trainee[i].getName() << endl;

最後にshowInformationを呼び出します。

trainee[i].showInformation();

プログラムの解答例

プロジェクト名/ファイル名: Prac3_3/ki_trainee.h

#ifndef _KI_TRAINEE_H_
#define _KI_TRAINEE_H_

#include <iostream>
#include <string>

using namespace std;

// 修行戦士クラス
class KiTrainee {
private:
    // 戦士名
    string m_name;

    // 年齢
    int m_age;

    // 流派
    string m_style;

    // 戦闘力
    int m_power;

public:
    // 戦士名のセッター
    void setName(string name);

    // 戦士名のゲッター
    string getName();

    // 年齢のセッター
    void setAge(int age);

    // 年齢のゲッター
    int getAge();

    // 流派のセッター
    void setStyle(string style);

    // 流派のゲッター
    string getStyle();

    // 戦闘力のセッター
    void setPower(int power);

    // 戦闘力のゲッター
    int getPower();

    // 修行戦士の情報を表示する
    void showInformation();
};

#endif // _KI_TRAINEE_H_

プロジェクト名/ファイル名: Prac3_3/ki_trainee.cpp

#include "ki_trainee.h"

// 戦士名を設定する
void KiTrainee::setName(string name) {
    m_name = name;
}

// 戦士名を取得する
string KiTrainee::getName() {
    return m_name;
}

// 年齢を設定する
void KiTrainee::setAge(int age) {
    m_age = age;
}

// 年齢を取得する
int KiTrainee::getAge() {
    return m_age;
}

// 流派を設定する
void KiTrainee::setStyle(string style) {
    m_style = style;
}

// 流派を取得する
string KiTrainee::getStyle() {
    return m_style;
}

// 戦闘力を設定する
void KiTrainee::setPower(int power) {
    m_power = power;
}

// 戦闘力を取得する
int KiTrainee::getPower() {
    return m_power;
}

// 修行戦士の情報を表示する
void KiTrainee::showInformation() {
    cout << m_name << ":" << m_style << " "
         << m_age << "歳 戦闘力" << m_power << endl;
}

プロジェクト名/ファイル名: Prac3_3/main.cpp

#include <iostream>
#include <string>
#include "ki_trainee.h"

using namespace std;

int main(int argc, char** argv) {
    // 2人分の修行戦士インスタンスを配列で生成する
    KiTrainee trainee[2];

    // 2人分の情報を入力する
    for (int i = 0; i < 2; i++) {
        // 入力用のローカル変数を宣言する
        string name;
        string style;
        int age;
        int power;

        // 何人目の情報を入力するかを表示する
        cout << "--- 戦士" << (i + 1) << "の情報を入力 ---" << endl;

        // 戦士名を入力する
        cout << "戦士名:";
        cin >> name;

        // 年齢を入力する
        cout << "年齢:";
        cin >> age;

        // 流派を入力する
        cout << "流派:";
        cin >> style;

        // 戦闘力を入力する
        cout << "戦闘力:";
        cin >> power;

        // セッターを使ってi番目のインスタンスに値を設定する
        trainee[i].setName(name);
        trainee[i].setAge(age);
        trainee[i].setStyle(style);
        trainee[i].setPower(power);

        cout << endl;
    }

    // 2人分の入力情報を確認する
    for (int i = 0; i < 2; i++) {
        cout << "--- 戦士" << (i + 1) << "の情報の確認 ---" << endl;
        cout << "戦士名:" << trainee[i].getName() << endl;
        cout << "年齢:" << trainee[i].getAge() << endl;
        cout << "流派:" << trainee[i].getStyle() << endl;
        cout << "戦闘力:" << trainee[i].getPower() << endl;
        cout << endl;
    }

    // showInformation関数を使って2人分の情報を表示する
    for (int i = 0; i < 2; i++) {
        trainee[i].showInformation();
    }

    // プログラムが正常に終わったことを示す
    return 0;
}

解説

問題3-3では、KiTraineeクラスのインスタンスを配列で2つ作っています。

KiTrainee trainee[2];

これにより、次の2つのインスタンスが生成されます。

配列要素意味
trainee[0]1人目の修行戦士
trainee[1]2人目の修行戦士

trainee[0]とtrainee[1]は、同じKiTraineeクラスから作られたインスタンスです。
ただし、持っているメンバ変数は別々です。

そのため、trainee[0]にLeoの情報を設定しても、trainee[1]には影響しません。
trainee[1]にNoaの情報を設定しても、trainee[0]には影響しません。

入力処理では、for文を使っています。

for (int i = 0; i < 2; i++) {

iは0、1と変化します。
そのため、trainee[i]は、順番にtrainee[0]、trainee[1]を表します。

セッターを呼び出す部分は、次のようになっています。

trainee[i].setName(name);
trainee[i].setAge(age);
trainee[i].setStyle(style);
trainee[i].setPower(power);

iが0なら、1人目のインスタンスに値が設定されます。
iが1なら、2人目のインスタンスに値が設定されます。

確認表示でもfor文を使っています。

cout << "戦士名:" << trainee[i].getName() << endl;
cout << "年齢:" << trainee[i].getAge() << endl;
cout << "流派:" << trainee[i].getStyle() << endl;
cout << "戦闘力:" << trainee[i].getPower() << endl;

ここでは、ゲッターを使って、各インスタンスが持っている値を取得しています。

最後に、showInformationをfor文で呼び出しています。

for (int i = 0; i < 2; i++) {
    trainee[i].showInformation();
}

trainee[0].showInformation()では、1人目の情報が表示されます。
trainee[1].showInformation()では、2人目の情報が表示されます。

同じshowInformation関数を呼び出していますが、使われるデータはインスタンスごとに違います。

呼び出し表示に使われるデータ
trainee[0].showInformation()trainee[0]のm_name、m_age、m_style、m_power
trainee[1].showInformation()trainee[1]のm_name、m_age、m_style、m_power

これが、複数インスタンスの大切なポイントです。

同じクラスから作られていても、インスタンスが違えば、持っている値も別々です。

ドラゴンボール風に言えば、KiTraineeという同じ戦士設計図から、LeoとNoaという2人の修行戦士を作っています。
同じ設計図を使っていても、Leoは亀仙流、Noaは神流というように、別々の情報を持てます。

3章の練習問題で確認したいポイント

今回の練習問題では、3章で学んだ内容をまとめて確認できます。

確認ポイント内容
クラスCapsuleItemクラス、KiTraineeクラスを作る
privateメンバ変数を外から直接触れないようにする
publicセッター、ゲッター、showInformationを外から使えるようにする
セッターprivateなメンバ変数に値を設定する
ゲッターprivateなメンバ変数から値を取得する
カプセル化内部データを守り、必要な操作だけ公開する
インスタンスクラスから実体を作る
配列同じクラスのインスタンスを複数作る
for文複数インスタンスに同じ処理を行う
showInformationクラス内のメンバ変数を使って情報を表示する

C++では、メンバ変数をpublicにすれば、外から簡単にアクセスできます。
しかし、自由に書き換えられるため、意図しない値が入る危険もあります。

そこで、メンバ変数はprivateにし、必要な操作だけをpublicなメンバ関数として公開します。

これは、ドラゴンボール風に言えば、戦士の本当の情報や修行アイテムの内部データを、修行カプセルの中に守る考え方です。

外からはセッターで値を設定する。
ゲッターで値を取得する。
showInformationで情報をまとめて表示する。
配列で複数のインスタンスを扱う。

この流れを練習問題で確認できれば、C++のクラス、カプセル化、複数インスタンスの基本がしっかり身についていきます。