先頭へ戻る

アクセス指定子 解答ページ | Programming Place Plus C++編【言語解説】 第12章

Programming Place Plus トップページ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++編を作成中ですが、今のところ、C++11 以降の C++ を詳しく解説できているコンテンツはありません。

問題①

問題① setter と getter を両方用意する代わりに、メンバ変数のメモリアドレスを返すメンバ関数を用意することは、良いアイディアでしょうか?


メンバ変数^のメモリアドレスを返すと、ポインタ経由で書き換えも読み取りも行えるようになります。実際問題、これは、メンバ変数を「公開」していることと何ら変わりありません。このような無制限な自由度を与えてしまうと、後からクラス内の実装を変更することが困難になるので、良いアイディアではありません。

問題②

問題② 「非公開」なメンバ関数は、どのような用途に使えるでしょうか?


「非公開」であるということは、そのクラスが自分で使うということです。これは、複数のメンバ関数が共通で必要となる処理をまとめたり、大きすぎる処理を分割したりといった用途に使えます。

問題③

問題③ 次の「正方形」を表す構造体について、カプセル化の観点から、問題点を指摘してください。

// 正方形を表す構造体
struct Square {
    int         mSide;    // 1辺の長さ
    int         mArea;    // 面積
};


class でなく struct なので、mSide、mArea はいずれも「公開」されています。そのため、外部から自由に書き換えが可能です。

すると問題なのは、mSide だけを書き換えたり、mArea だけを書き換えたりできてしまうことです。mSide は「1辺の長さ」で、mArea は「面積」なので、本来、mSide が変化したら、連動して mArea も変化しなければいけませんし、逆も同様です。

このような、連動しなければならない情報へは自由なアクセスを許してはいけません。必ず、正しく連動することを保証する関数を用意して、その関数経由でのアクセスのみを許すように設計しましょう。次のようにすると良いでしょう。

// 正方形を表すクラス
class Square {
public:
    void SetSide(int side);

    int GetSide() const;
    int GetArea() const;

private:
    int         mSide;    // 1辺の長さ
    int         mArea;    // 面積
};

void Square::SetSide(int side)
{
    assert(side > 0);

    mSide = side;
    mArea = mSide * mSide;
}

int Square::GetSide() const
{
    return mSide;
}

int Square::GetArea() const
{
    return mArea;
}

ここでは、「1辺の長さ」だけを設定できるようにして、「面積」を直接書き換えないようにしています。なお、「面積」をメンバ変数として持たずに、必要なときに計算するという設計も考えられます。その方針に沿って変形すると、次のようになります。

// 正方形を表すクラス
class Square {
public:
    void SetSide(int side);

    int GetSide() const;
    int GetArea() const;

private:
    int         mSide;    // 1辺の長さ
};

void Square::SetSide(int side)
{
    assert(side > 0);

    mSide = side;
}

int Square::GetSide() const
{
    return mSide;
}

int Square::GetArea() const
{
    return mSide * mSide;
}

メンバ変数が「非公開」にしてあれば、このように実装を変更しても、クラスを使っている側には何も修正が要りません。これもカプセル化の重要な利点です。


参考リンク


更新履歴

’2014/4/24 新規作成。



第12章のメインページへ

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

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
Twitter でツイート Twitter をフォロー LINE で送る
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー