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

トップページModern C++編 C++編](../../index.html) – 第6章

Modern C++編は作りかけで、更新が停止しています。代わりに、C++14 をベースにして、その他の方針についても見直しを行った、新C++編を作成しています。
Modern C++編は削除される予定です。

問題①

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


たとえば、次のような実装になります。

class Student {
public:
    int* GetScorePtr()
    {
        return &mScore;
    }

private:
    int          mScore;  // 得点
};

このように、メンバ変数のメモリアドレスを返すと、ポインタ経由で書き換えも読み取りも行えるようになります。

Student s;
*(s.GetScorePtr()) = 10;  // OK

これができてしまうということは、もはや「s.mScore = 10;」ができることと何ら変わりは無く、 assert を入れ込むなどの余地も無くなってしまいます。 後からクラス内の実装を変更することも困難になるので、良いアイディアではありません。


問題②

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


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


問題③

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

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


class でなく struct になっており、明示的なアクセス指定子もないので、mSide、mArea はいずれも「公開」されています。そのため、外部から自由に書き換えが可能です。

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

このような、連動しなければならない情報へは自由なアクセスを許してはいけません。必ず、正しく連動することを保証する関数を用意して、その関数経由でのアクセスのみを許すように設計しましょう。たとえば、「1辺の長さ」だけを設定できるようにして、「面積」を直接書き換えないようにすると、以下のようになります。

// 正方形を表すクラス
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;
}

あるいは、「面積」をメンバ変数として持たずに、必要なときに計算するという設計も考えられます。 その方針に沿って変形すると、次のようになります。

// 正方形を表すクラス
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;
}

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


参考リンク


更新履歴

’2017/7/14 新規作成。



第6章のメインページへ

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

Programming Place Plus のトップページへ



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