質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

20603閲覧

相互参照の設計的な良し悪しについて

damalnylpo

総合スコア53

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2016/07/21 12:18

編集2016/07/21 12:23

###質問したいこと
相互参照というのはもっともな回避法があるのでしょうか?
また、相互参照はそれほど回避する必要があるのでしょうか?

###相互参照の評価

c++

1//生きてる 2class Unit{ 3public: 4 int Damage(int)//めちゃくちゃ痛いことする 5private: 6 weak_ptr<Field> field; 7} 8 9//生きてるの持ってる 10class Field{ 11private: 12 vector<shared_ptr<Unit>> units; 13} 14

こういう形の実装は良くないと言われているのを耳にしました。

確かにFieldがUnitを参照しているのにUnitもまたFieldを参照してしまうと
クラス関係が複雑になったりモジュール結合が強いというのはわかります。
ですがこのプログラムがゲームだとしてUnitがUnitに対してダメージを与えたりする場合
Unitへアクセスする必要があり
Unit自体はUnitへの参照を持たないので
その攻撃範囲なりなんなりにUnitがいるのかどうかどうにかして調べる必要があり、
そのためには各Unitを持っているFieldクラスにアクセスする必要があると思います。

これを相互参照に使用せずに回避する方法があるのでしょうか?
実装する場合Unitはインターフェースになると思いますが
どちらにせよFieldへの相互参照になるのは変わりないはずです。

###パッと思いつく回避法

  1. アクセスが必要なものはすべてFieldが行い戻り値と引数を駆使する

これをすると移動などもFieldクラスが管理する必要があり
Unitとのアクセスもやたら増えますし、変更に弱く
Fieldクラスが肥大化し介護福祉士と名を変える必要が出てしまうと思います。
それに手続き型でよくなります。

  1. フィールドをグローバル

結合度が高くなるのは変わりないと思います

  1. UnitにUnit全てへの参照を持たせる

これは・・・

  1. フィールドへの参照をインターフェースでラップする

Fieldクラスの参照自体は隠せますし結合度は下がるかもしれませんが釈然としません。
これは相互参照自体の解決にはなってないような気もしないでもありません。

  1. クラス構成をリフォームする

個人的にこのクラス分けが直感的なので
出来ればなんとかManagerとかがたくさん出てくる
劇的な匠業は遠慮したいです。

###実際のところどうなんでしょうか
何か上手い回避方法があるのでしょうか?
そもそも相互参照はそこまで気にしないでいいのでしょうか?
調べても良くないという人もいれば場合によっては選択肢に入るという人もいますが
今一つはっきりとした答えが見つかっていません。
今回のFieldクラスとUnitクラスでいうとUnitはFieldの参照を持つべきなのでしょうか?
答えがあるとすればその理由を教えていただきたいです。
ちなみに相互参照を持つとすればsharedとweakの使い方は間違っていませんか?

opensourceのゲームも少し調べてみましたがUnitのリストを持つクラスがグローバルなものと
Fieldへの参照(生ポインタでした)を持っているタイプしかまだ見ていません。
というかその二つしかまだ調べてません!!!!!

maisumakun👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

こういう形の実装は良くないと言われているのを耳にしました。

可能な時は避けましょうであって、何が何でも避けましょうではないと思います。
安易な設計の結果、相互参照になるのは非常にやばいので、それなりに頑張って避けるべきとは思います。

でも、FieldとUnitの例のようにそれを用いることが自然な場合にまで無理に避けるのは却って良くないと思います。
ツリー構造の時には結構頻繁に必要になりそうな気がします。
親は当然子への参照を持ちますが、子が親の情報を必要とするケースはそこそこある筈です。


【追記】

ちなみに相互参照を持つとすればsharedとweakの使い方は間違っていませんか?

回答が漏れてました。使い方は間違ってないと思います。両方ともshared_ptr<>にしたらリークしますから。

投稿2016/07/21 12:40

編集2016/07/21 13:38
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

damalnylpo

2016/07/21 13:39 編集

回答ありがとうございます! 再帰処理などのようにデメリットを認識せずむやみに使うことがいけないということでよさそうですね。 ツリー構造はおそらく親子のクラス自体は同じかもしれませんが 確かに親への参照はありそうです。 これで安心して相互参照を使っていけそうです。 ありがとうございました! 追記ありがとうございます!
Chironian

2016/07/21 13:41

> ツリー構造はおそらく親子のクラス自体は同じかもしれませんが いいえ、そうでもないです。分岐と葉は普通クラスが異なります。 フォルダとファイルの関係みたいな感じですね。
damalnylpo

2016/07/21 13:51

なるほど・・・ 多階層のツリーの場合は自身への参照を持つ必要があるので 二階層構造のFieldとは少し違うかとはやとちりしましたが ファイルを管理するクラスから見たインターフェースが同じなだけで 確かにディレクトリとファイル同士の関係は異なるクラスの親子関係でFieldと一致しますね。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問