トップページ – Modern C++編 C++編](../../index.html) – 第6章
問題① 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);
= side;
mSide = mSide * mSide; // 面積も書き換える
mArea }
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);
= side;
mSide }
int Square::GetSide() const
{
return mSide;
}
int Square::GetArea() const
{
return mSide * mSide;
}
メンバ変数が「非公開」にしてあれば、このようにメンバ変数が増減しても、クラスを使っている側には何も修正が要りません。これもカプセル化の重要な利点です。
新規作成。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |