入れ子クラスとローカルクラス 解答ページ | Programming Place Plus C++編【言語解説】 第24章

トップページC++編

C++編で扱っている C++ は 2003年に登場した C++03 という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14 -> C++17 -> C++20 と更新されており、今後も 3年ごとに更新されます。
なかでも C++11 での更新は非常に大きなものであり、これから C++ の学習を始めるのなら、C++11 よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。

問題①

問題① Studentクラスと Score入れ子クラスの例を拡張して、その生徒の各学期末(1学期、2学期、3学期)の成績を管理するようにしてください。各教科の得点は、以下のように与えられているものとします。

const Student::Score SCORES[] = {
    Student::Score(90, 60, 71),
    Student::Score(84, 70, 65),
    Student::Score(92, 67, 73),
};


#include <cassert>
#include <iostream>
#include <string>
#include <vector>

#define SIZE_OF_ARRAY(array) (sizeof(array)/sizeof(array[0]))

class Student {
public:
    class Score {
    public:
        Score(int japanese, int math, int english);

    public:
        int GetAverage() const;

    private:
        enum Subject {
            SUBJECT_JAPANESE,
            SUBJECT_MATH,
            SUBJECT_ENGLISH,

            SUBJECT_NUM,  // 総数を表すダミー
        };

    private:
        int  mScores[SUBJECT_NUM];
    };

    typedef std::vector<Score>  Scores_t;

    static const int SCORE_DATA_NUM = 3;

public:
    Student(const std::string& name, const Scores_t& scores) :
        mName(name),
        mScores(scores)
    {
        assert(mScores.size() == SCORE_DATA_NUM);
    }

public:
    inline const std::string& GetName() const
    {
        return mName;
    }

    inline const Score& GetScore(int term) const
    {
        assert(0 <= term && term < SCORE_DATA_NUM);
        return mScores[term];
    }

private:
    const std::string  mName;
    const Scores_t     mScores;
};

Student::Score::Score(int japanese, int math, int english)
{
    mScores[SUBJECT_JAPANESE] = japanese;
    mScores[SUBJECT_MATH] = math;
    mScores[SUBJECT_ENGLISH] = english;
}

int Student::Score::GetAverage() const
{
    int sum = 0;
    for (int i = 0; i < SIZE_OF_ARRAY(mScores); ++i) {
        sum += mScores[i];
    }
    return sum / SIZE_OF_ARRAY(mScores);
}


int main()
{
    const Student::Score SCORES[Student::SCORE_DATA_NUM] = {
        Student::Score(90, 60, 71),
        Student::Score(84, 70, 65),
        Student::Score(92, 67, 73),
    };

    Student student("Tanaka Miki", Student::Scores_t(SCORES, SCORES + Student::SCORE_DATA_NUM));

    std::cout << "Name: " << student.GetName() << "\n"
        << "  1st term Average: " << student.GetScore(0).GetAverage() << "\n"
        << "  2nd term Average: " << student.GetScore(1).GetAverage() << "\n"
        << "  3rd term Average: " << student.GetScore(2).GetAverage() << std::endl;
}

実行結果:

Name: Tanaka Miki
  1st term Average: 73
  2nd term Average: 73
  3rd term Average: 77

Studentクラスの mScore を拡張して、3学期分のデータを保持できるようにする必要があります。生の配列でも構いませんが、今回は vector(【標準ライブラリ】第5章)を使用しました(STLコンテナを積極的に使ってみることをします)。

問題②

問題② Printerローカルクラスの例を変形して、ローカル関数のような使い方をするプログラムを作成してください。


ローカルクラスに、staticメンバ関数を持たせれば簡単です。

#include <iostream>

int main()
{
    class Printer {
    public:
        static void Puts(const char* str, const char* begin = "", const char* end = "")
        {
            std::cout << begin << str << end << std::endl;
        }
    };

    Printer::Puts("Test Message1");
    Printer::Puts("Test Message2", "[[", "]]");
    Printer::Puts("Test Message3", "[[", "]]");
}

実行結果:

Test Message1
[[Test Message2]]
[[Test Message3]]


参考リンク


更新履歴

’2018/7/13 サイト全体で表記を統一(「静的メンバ」–>「staticメンバ」)

’2016/1/9 新規作成。



第24章のメインページへ

C++編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る