お久しぶりです。覚えている方いないでしょうかね。
去年の冬くらいに登録して、何度か掲示板を利用させていただいたものです。
回答していただいた方、お世話になりました!
現在、C++&DxLibでシューティング制作しています。
C++初心者です。まあCもまだまだ初心者の域でしょうけど。
アニメーション管理クラスというものを作りました。スクリプト式にaddAnimMove(…),addAnimBright(…)のようにアニメーション情報を追加していって、毎レートごとに一括アニメーションさせるものです。
set系とDrawRotaGraphしか使っていないので、縦横伸縮アニメーションはできないんですけどね。
それ自体は何か月もかけてやっと完成したのですが、オブジェクト指向の勉強になっているのかどうか。
オブジェクト指向の勉強になっていないと思うのは、virtual,friendのような関数と、継承といった機能を、まだ一度も使ったことがないんです。
今までは、使うタイミングになったら、この機能は今のような状況で使うんじゃないかと多少は想像できたんですけど、なかなかこれは分かりません。
日本は国だから、国クラスを継承して、派生クラス日本を作る、それは分かるんです。
種類ごとに分類していくだけなら簡単な話なんですけど、実際の処理になると分からなくなるんですね。
マウス入力クラスを継承して移動クラスを作る、これは正しいと思いますか?
前述のアニメーション管理クラスを作ろうとした時、初めはイメージ管理クラスを継承してアニメーション管理クラスを作ろうとして、大失敗→アドバイスを頂き一から作り直し、になったのでとにかくやってみるのも少し怖い
オブジェクト指向って機能は多いし、やっていることは複雑だし、難しいんですね。
そもそもポインタ自体理解しているのだろうか。
いきなり現れて、変な日記になってごめんなさい。
まあ完成を目指して間違ったことをしてもいいから作っていくしかないですよね。
ではでは長文失礼しました
日記
- bitter_fox
- 記事: 607
- 登録日時: 14年前
RE: 日記
種類で継承というよりかは機能で継承すると考えたほうが良いと思います。paw さんが書きました: 日本は国だから、国クラスを継承して、派生クラス日本を作る、それは分かるんです。
種類ごとに分類していくだけなら簡単な話なんですけど、実際の処理になると分からなくなるんですね。
マウス入力クラスを継承して移動クラスを作る、これは正しいと思いますか?
前述のアニメーション管理クラスを作ろうとした時、初めはイメージ管理クラスを継承してアニメーション管理クラスを作ろうとして、大失敗→アドバイスを頂き一から作り直し、になったのでとにかくやってみるのも少し怖い
この例だと、日本クラスが国クラスを継承するのは日本国が国クラスの持つ機能を持つからですよね?(国クラスをマーカー的に使うのであれば別ですが・・・)
こう考えるとアニメーション管理クラスにはイメージを管理する機能は必要ではないのでイメージ管理クラスを継承する必要が無いのも簡単に理解できるのではないでしょうか?(管理するのはアニメーションであってイメージではないですよね?そう考えたのですが違ってたらすみません)
ただ、機能が必要でも親クラスと子クラスの関係が飛躍し(種類が違い)すぎているものは、プログラムがカオスになるので継承するべきではありません。
例えば、州クラスが国クラスの機能を必要だからと言って国クラスを継承するのはおかしいですよね?(もし継承してしまったら州が国連に加盟出来てしまったり・・・)
この場合は、委譲を使って実装します。
これらをまとめると、まず継承しようとしているクラスの機能が必要かを考えてから、その親クラスと子クラスの関係性が間違っていないかを考えると良いと思います。
マウス入力クラスがどのレベルの処理を担うのかが分からないのですが、仮にマウス入力があった際にどこかに登録されているマウス入力クラスの子クラスすべてが呼び出されるようなシステムなのであれば、移動クラス(これもどのようなクラスかが分からないのでアレですが・・・)がそのクラスを継承するのは間違って無いでしょう。
Re: 日記
アドバイス有難うございます。
委譲という言葉、聞いたことなかったので参考になりました
調べてみると不要な機能を除いた継承という感じで、州と国のたとえはとても分かりやすかったです。
アニメーション管理クラスというのは・・・。
まずイメージ管理クラスを作りました。
イメージをオブジェクトのように管理して、例えばImg.setBright(color構造体);のように一発でそのイメージ情報を変化させることができるようにしたものです。
それにアニメーションクラス(内部にスタックのようなものがあってアニメーションを積み重ねていく)をポインタで関連付けて、オブジェクト単位でお互い一対一で管理できるようにしたものがアニメーション管理クラスです。
>>アニメーション制御用のメンバ関数を持つAnimatedObject といったクラスを作って継承させると思います。
今後はさらに機体オブジェクトクラスを作って、機体オブジェクトと、Img,Animがそれぞれ同じ配列番号を持たせて例の通り一対一でポインタで関連付けさせようと思っていたんですけど…。
継承、ですか・・・
この「ポインタで関連付ける」という方法もアニメーション管理クラス作り直しの際に教えて頂いたのですが、「継承」や「委譲」のうような何か言葉ないんですかね・・・。
色々アドバイスいただけてありがたいのですが、
>>関係性が間違っていないか
この「関係性」が間違っているのか、正しいのか、が分からないので間違えるんですよ。
というより自分が現状を伝えきれていないですかね。ごめんなさい。
日本語変かな・・・
この「ポインタでオブジェクトごとに関連付ける」の言葉あれば教えて頂けるとありがたいです
委譲という言葉、聞いたことなかったので参考になりました
調べてみると不要な機能を除いた継承という感じで、州と国のたとえはとても分かりやすかったです。
アニメーション管理クラスというのは・・・。
まずイメージ管理クラスを作りました。
イメージをオブジェクトのように管理して、例えばImg.setBright(color構造体);のように一発でそのイメージ情報を変化させることができるようにしたものです。
それにアニメーションクラス(内部にスタックのようなものがあってアニメーションを積み重ねていく)をポインタで関連付けて、オブジェクト単位でお互い一対一で管理できるようにしたものがアニメーション管理クラスです。
>>アニメーション制御用のメンバ関数を持つAnimatedObject といったクラスを作って継承させると思います。
今後はさらに機体オブジェクトクラスを作って、機体オブジェクトと、Img,Animがそれぞれ同じ配列番号を持たせて例の通り一対一でポインタで関連付けさせようと思っていたんですけど…。
継承、ですか・・・
この「ポインタで関連付ける」という方法もアニメーション管理クラス作り直しの際に教えて頂いたのですが、「継承」や「委譲」のうような何か言葉ないんですかね・・・。
色々アドバイスいただけてありがたいのですが、
>>関係性が間違っていないか
この「関係性」が間違っているのか、正しいのか、が分からないので間違えるんですよ。
というより自分が現状を伝えきれていないですかね。ごめんなさい。
日本語変かな・・・
この「ポインタでオブジェクトごとに関連付ける」の言葉あれば教えて頂けるとありがたいです
Re: 日記
オブジェクトが必ず固有の1つの画像とアニメーションしか持たないならpaw さんが書きました: >>アニメーション制御用のメンバ関数を持つAnimatedObject といったクラスを作って継承させると思います。
今後はさらに機体オブジェクトクラスを作って、機体オブジェクトと、Img,Animがそれぞれ同じ配列番号を持たせて例の通り一対一でポインタで関連付けさせようと思っていたんですけど…。
その方法でもいいかも知れませんが、
一つの画像やアニメーションを複数のオブジェクトで共有したり、
一つのオブジェクトが複数の画像を持つような設計ができなくなるので、
個人的にオブジェクトと画像とアニメーションクラスを一対一で対応させるのはお勧めしません。
最後に編集したユーザー h2so5 on 2011年9月01日(木) 17:45 [ 編集 1 回目 ]
RE: 日記
継承は何が何でも使わなくてはならないもの、「ではない」というのが自分の考え方です。
むしろ継承は「必要でなければ避けるべきもの」とさえ思います。
bitter_foxさんが機能で継承する的なことをおっしゃっていましたが、それに付け加えるなら
自分が継承を(厳密にはpublic継承を)使うのは以下の場合です。
①派生クラスは基底クラスとして「完全に」ふるまうことができる。
②そして実際に「ふるまわせたい」。(つまりアップキャストが必要)
以上の2点は最低でも満たさないと継承は使いません。
また自分が継承を使わない場合もいくつかありますが、この場合もっとも近いのは以下の場合です
「機能を必要としているだけで、基底クラスとしてふるまう必要がない。」
この場合はコンポジット、具体的にはメンバ変数としてその機能を持つクラスを所有してしまえばいいわけです。
マウス入力クラスを継承して移動クラスを作る
これが代表的なものだと思います。移動クラスが、マウス入力クラスの機能を必要としているかもしれませんが、
「決して」移動クラスはマウス入力クラスではないのです。(言い換えれば移動クラスはマウス入力クラスとしてふるまわないでしょう)
この場合に継承を使うべきではないというのが自分の意見です。
イメージ管理クラスを継承してアニメーション管理クラスを作る
同様です。アニメーション管理クラスはイメージ管理クラスなのですか?またイメージ管理クラスとして「ふるまう必要が生じていますか?」
おそらく否だと思います、継承は必要ないというのが自分のやり方になるでしょう
さらにいうと
自機や敵や弾は全てアニメーションの情報を持っているはずなので、
アニメーション制御用のメンバ関数を持つAnimatedObject といったクラスを作って継承させる
これもおそらく自分ならやらないと思います、理由はもう冗長なので大きく省略しますが、
敵は、自機は、弾はAnimatedObject としてふるまう必要がないからです(もしくはそうしなくていい実装ができるからです)
ここに挙げられているので自分的に納得がいったのは
日本は国だから、国クラスを継承して、派生クラス日本を作る
これです。これは日本を国としてふるまわせる必要が生じていて、しかも日本が国として完全にふるまうでしょうから継承が必要だと思います。
以上ですが、あくまでも一意見としてどうぞ。
むしろ継承は「必要でなければ避けるべきもの」とさえ思います。
bitter_foxさんが機能で継承する的なことをおっしゃっていましたが、それに付け加えるなら
自分が継承を(厳密にはpublic継承を)使うのは以下の場合です。
①派生クラスは基底クラスとして「完全に」ふるまうことができる。
②そして実際に「ふるまわせたい」。(つまりアップキャストが必要)
以上の2点は最低でも満たさないと継承は使いません。
また自分が継承を使わない場合もいくつかありますが、この場合もっとも近いのは以下の場合です
「機能を必要としているだけで、基底クラスとしてふるまう必要がない。」
この場合はコンポジット、具体的にはメンバ変数としてその機能を持つクラスを所有してしまえばいいわけです。
マウス入力クラスを継承して移動クラスを作る
これが代表的なものだと思います。移動クラスが、マウス入力クラスの機能を必要としているかもしれませんが、
「決して」移動クラスはマウス入力クラスではないのです。(言い換えれば移動クラスはマウス入力クラスとしてふるまわないでしょう)
この場合に継承を使うべきではないというのが自分の意見です。
イメージ管理クラスを継承してアニメーション管理クラスを作る
同様です。アニメーション管理クラスはイメージ管理クラスなのですか?またイメージ管理クラスとして「ふるまう必要が生じていますか?」
おそらく否だと思います、継承は必要ないというのが自分のやり方になるでしょう
さらにいうと
自機や敵や弾は全てアニメーションの情報を持っているはずなので、
アニメーション制御用のメンバ関数を持つAnimatedObject といったクラスを作って継承させる
これもおそらく自分ならやらないと思います、理由はもう冗長なので大きく省略しますが、
敵は、自機は、弾はAnimatedObject としてふるまう必要がないからです(もしくはそうしなくていい実装ができるからです)
ここに挙げられているので自分的に納得がいったのは
日本は国だから、国クラスを継承して、派生クラス日本を作る
これです。これは日本を国としてふるまわせる必要が生じていて、しかも日本が国として完全にふるまうでしょうから継承が必要だと思います。
以上ですが、あくまでも一意見としてどうぞ。
Re: 日記
長くなって、おまけに掲示板みたいな使い方になってしまってすみません。
ちょっと、今実際に継承から、「コンポジット式」に変更しようとして(入力関連は昨日の時点でいったん継承で作っていました)気づいたことですが、protected(メンバの指定子の方の)みたいなことができないんですね。
継承を避けるべきというのは、それぞれの関係がグチャグチャになってしまうからでしょうけど、わざわざ全privateメンバをゲッター、セッター操作にしてまで避けるべきか、ってとこが個人的には気になります。
まだまだ素人なので、それを解決するいい方法があるのかもしれませんけど。
その辺どうされているんでしょう?
コンポジット式の方法を使ったとき、基底クラスのprivateに相当するprivateメンバにアクセスしようとするときは全部ゲッター、セッターにされているんでしょうか。
それともほかに良い方法があるんでしょうか・・・。
今後の為にも教えていただけると嬉しいのですが・・・
ちょっと、今実際に継承から、「コンポジット式」に変更しようとして(入力関連は昨日の時点でいったん継承で作っていました)気づいたことですが、protected(メンバの指定子の方の)みたいなことができないんですね。
継承を避けるべきというのは、それぞれの関係がグチャグチャになってしまうからでしょうけど、わざわざ全privateメンバをゲッター、セッター操作にしてまで避けるべきか、ってとこが個人的には気になります。
まだまだ素人なので、それを解決するいい方法があるのかもしれませんけど。
その辺どうされているんでしょう?
コンポジット式の方法を使ったとき、基底クラスのprivateに相当するprivateメンバにアクセスしようとするときは全部ゲッター、セッターにされているんでしょうか。
それともほかに良い方法があるんでしょうか・・・。
今後の為にも教えていただけると嬉しいのですが・・・
Re: 日記
結論から言いますと、必要なものはゲッタとセッタを使うことになります。paw さんが書きました: 継承を避けるべきというのは、それぞれの関係がグチャグチャになってしまうからでしょうけど、わざわざ全privateメンバをゲッター、セッター操作にしてまで避けるべきか、ってとこが個人的には気になります。
・・・
コンポジット式の方法を使ったとき、基底クラスのprivateに相当するprivateメンバにアクセスしようとするときは全部ゲッター、セッターにされているんでしょうか。
・・・そしてもっといいますと、メンバ変数はほぼ例外なくprivateにするべきです。たとえ継承を使っても使わないでもです。(Cの構造体的に使うようなデータのまとまりは除きます)
たとえ派生クラスであっても基底クラスのメンバ変数に直にアクセスできるような設計はよくないのです。(つまるところメンバ変数がprotectedになることはない)
「わざわざ全privateメンバをゲッター、セッター操作にしてまで」とありますが、大切なことなのです。
自分の場合基底クラスの変数そのものがほしければ、それもゲッターとセッターを介します。
そしてそれらは「必要なだけ作ればいい」のです。メンバ変数そのものを(つまり参照やポインタを)外部(派生クラスを含む)から引っ張り出す必要が生じることなど少数なはずです。
たとえば、C++のstringクラスには、おそらくたくさんのメンバ変数があるでしょうが、実質的に取り出せるのはchar型ポインタ(および参照)だけです。
もし全部作る必要が生じたならば、そのときは一度立ち止まって本当にこれでいいかを考えるようにしています。(たいていの場合は自分の実装がまずいとわかります)