- ベストアンサー
オブジェクト指向 集約の実装について
例えば、 学校クラス--学年クラス--学級クラス--班クラス というクラスがあった場合、それぞれのクラスには集約といわれる関連があると思いますが、この場合の実装は一般的にどのようにされているのでしょうか。 自分の考えでは、 class Gakko { vector<Gakunen> GakunenObj; }; class Gakunen { vector<Gakkyu> GakkuObj; }; class Gakku { vector<Han> HanObj; } class Han { void ShowName(); } このように学校クラスが消えれば内包される学年クラス・学級クラス・班クラスも消える必要があるので、オブジェクトの寿命を親のクラスと同じにするため、各クラスに子クラスのインスタンスを持たせています。 この方法だと班の名前を表示したい場合、 Gakko Obj; Obj.GakunenObj[a].GakkuObj[b].HanObj[c].ShowName(); といった感じでアクセスすることになると思います。 ただ、こんな長たらしいプログラムコードを見たこともありませんし、実際は通常の関連としてクラスのポインタを持たせた方がいいでしょうか。 突っ込みどころ満載ですが、よろしくお願い致します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>この方法だと班の名前を表示したい場合、 >Gakko Obj; >Obj.GakunenObj[a].GakkuObj[b].HanObj[c].ShowName(); >といった感じでアクセスすることになると思います。 上記の例の場合、直接Hanに対してアクセスするのではなく、 Gakko Obj; ... Gakko の中身生成 ... const Gakunen& GakunenObj = Obj.Gakunen[a]; const Gakku& GakkuObj = GakuenObj.GakkuObj[b]; const Han& HanObj = GakkuObj.HanObj[c]; HanObj.ShowName(); のような流れになると思います。 また、個人的にはGakkoオブジェクトから直接班の名前を参照する、という状況自体が間違っているのだと思います。 大概「どこのクラスのどこの班の名前だけを表示する」という状況は余りなく、学年単位、クラス単位で処理を行うことが多いと思います(そのためにクラスが別になっているわけですし)。 なので、オブジェクト指向的には、「班の名前を表示する」というのが実は「その学校に所属している班の一覧を表示する」という処理の一部だとしたら、Gakkoクラスに所属している班の一覧を表示するというメソッドを実装するのがより正しいと思います。
その他の回答 (3)
- i-kujou
- ベストアンサー率50% (13/26)
>const Gakunen& GakunenObj = Obj.Gakunen[a]; >const Gakku& GakkuObj = GakuenObj.GakkuObj[b]; >const Han& HanObj = GakkuObj.HanObj[c]; >HanObj.ShowName(); >で参照を使ってアクセスすることの方がよいメリットというのがいまいち分かりません。(前者の方がオーバーヘッドが大きいとか、コードが読みにくくなるとかでしょうか?) この場合はHanObj.ShowName();単体ですからメリットが見えませんが、オブジェクト指向プログラムで組んでいると、大概において「同じオブジェクト群に対して複数の操作を行う」ということが良くあります。 例えば、あるクラスの班員全員の名前を表示して着席させる、という場合、 const Gakunen& GakunenObj = Obj.Gakunen[a]; const Gakku& GakkuObj = GakuenObj.GakkuObj[b]; cont int n = GakkuObj.length(); for( int i=0; i<n; ++i) { const Han& HanObj = GakkuObj.HanObj[c]; HanObj.ShowName(); HanObj.SitDown(); } というコーディングになります。 HanObjのオブジェクトを取り出すのにアドレスの計算は ・ObjからGakunenObjを取り出すのが1回 ・GakunenObjからGakkuObjを取り出すのが1回 ・GakkuObjからHanObjを取り出すのがn回(=Hanの数) となり、合計n+2回です。 これを cont int n = Obj.GakunenObj[a].GakkuObj[b].length(); for( int i=0; i<n; ++i) Obj.GakunenObj[a].GakkuObj[b].HanObj[i].ShowName(); Obj.GakunenObj[a].GakkuObj[b].HanObj[i].SitDown(); } とした場合、同じことをしているはずなのに、アドレスの計算は ・GakkenObj[a] ・GakkuObj[b] ・HanObj[i] をforループのたびに計算しなおしていますから、n×3×2回(ShowNameとSitDownの分)となり、参照を利用した場合と比べ6倍近いアドレス計算量が必要となります。 最近のコンパイラですと上記のような単純な計算については最適化してくれるかもしれませんが、量が増えれば増えるほどバカにならない重さになる場合があります。 また、単純に添え字が大量にあるよりも現在どのオブジェクトを操作しているのか、パッとみで分かりやすい、というのもメリットかと思います。 あと、個人的にはちゃんとしたオブジェクト指向の本を一度読まれることをお勧めします。
お礼
お返事ありがとうございます。 分かりやすくて大変勉強になりました。 オブジェクト指向の本は1冊しかまだ読んでいませんので他にもいろいろ読んでみたいと思います。 あと、基本的な本しか読んだことがないので他の人が書いたコードもたくさん読んで、コーディングのスタンダード?を知ったほうが良さそうですね。
- Tacosan
- ベストアンサー率23% (3656/15482)
いきなり Obj.GakunenObj[a].GakkuObj[b].HanObj[c].ShowName(); なんてアクセスをするのかなぁ? 参照で逃げられることも多いような気がするけど.... ところで, 「クラスのポインタを持たせる」として, どのような実装を考えていますか?
- chie65536(@chie65535)
- ベストアンサー率44% (8755/19867)
>クラスのポインタを持たせた方がいいでしょうか。 int array[20][20][30][10][30]; array[a + 1][b][c1 * 3 + c2][d][e1 + e2] = 13 - array[a + 1][b][c1 * 3 + c2][d][e1 + e2]; n = array[a + 1][b][c1 * 3 + c2][d][e1 + e2] + 22; array[a + 1][b][c1 * 3 + c2][d][e1 + e2] = n + array[a + 1][b][c1 * 3 + c2][d][e1 + e2 + 1]; と int array[20][20][30][10][30]; int *p = &array[a + 1][b][c1 * 3 + c2][d][e1 + e2]; *p = 13 - *p; n = *p + 22; *p = n + *(p + 1); と、どっちの方が良いと思いますか? 答え、聞くまでもありませんよね。
お礼
お返事ありがとうございます。 参照を利用してアクセスできるんですね。 あとご指摘の通り、Gakkoクラスに適切な操作としては「所属している班の名前を一覧表示する」が適切ですね。 集約の実装としては、親クラスに子クラスのインスタンスを持たせ、参照を利用して子クラスの目的の操作にアクセスする。 という事でよろしいでしょうか。 あと、 Obj.GakunenObj[a].GakkuObj[b].HanObj[c].ShowName(); で直接アクセスすることに比べ、 const Gakunen& GakunenObj = Obj.Gakunen[a]; const Gakku& GakkuObj = GakuenObj.GakkuObj[b]; const Han& HanObj = GakkuObj.HanObj[c]; HanObj.ShowName(); で参照を使ってアクセスすることの方がよいメリットというのがいまいち分かりません。(前者の方がオーバーヘッドが大きいとか、コードが読みにくくなるとかでしょうか?)