C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: 継承について


(過去ログ 51 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■28317 / inTopicNo.1)  継承について
  
□投稿者/ ねこ中尉 (1回)-(2008/11/24(Mon) 13:20:45)

分類:[C/C++] 

こんにちは。

VC++6.0で、MFCを利用した開発を行っています。

継承について教えてください。

現在、下記のような形でクラスが存在しています。
ClassA(FuncA)
- ClassA-1
- ClassA-2
- ClassA-3
- ClassA-4
(ClassA-1はClassAを継承している・・・というイメージです)
(ClassAは、メンバ関数FancAを持っています)

ここで、ClassB(ClassAを継承し、ClassAの持つメンバ関数FuncAをオーバーライド
して、一部改変している)を作成し、別機能の新たな基底クラスとして利用すること
になりました。
ClassA(FuncA)
- ClassB(FuncA)
-- ClassB-1
-- ClassB-2
-- ClassB-3
-- ClassB-4

ただ、ClassA-1とClassB-1など、派生郡については、全く同じ内容で問題ないため、
ClassA-1
- ClassB-1
といった継承関係も作りたいと考えています。

ClassB-1でFuncAを呼んだ場合、ClassBで改変してあるFancAを使用したいのですが、
このような場合、どのような形で継承を行えばよろしいのでしょうか。

ClassAを仮想クラスとして継承すれば、期待通りの動作が可能となるのでしょうか。

宜しくお願い致します。
引用返信 編集キー/
■28320 / inTopicNo.2)  Re[1]: 継承について
□投稿者/ 倉田 有大 (360回)-(2008/11/24(Mon) 15:52:27)
2008/11/24(Mon) 15:54:30 編集(投稿者)
ぬう、ちょっと名前がわかりにくいな。
class O(virtual FuncO()) → class A(virtual FuncO()) → class A1(virtual FuncO())
                                                      → class A2(virtual FuncO())
                         → class B(virtual FuncO()) → class B1(virtual FuncO())
                                                      → class B2(virtual FuncO())

名前を勝手にかえてみました。

O a = new B2();
a.FuncO();

て、C++か、C#かとおもった、失礼。
C#は多重継承禁止されてるので、

>ClassA-1
>- ClassB-1
>といった継承関係も作りたいと考えています。

これ、どうなるのか、さっぱりわすれたなあ。

まあ、関数をオーバーライドしてやれば、インスタンスを生成した、クラスの関数がよばれますよ。
こういう事きいてるんじゃないのかな?

引用返信 編集キー/
■28325 / inTopicNo.3)  Re[1]: 継承について
□投稿者/ dogatana (9回)-(2008/11/24(Mon) 16:30:39)
No28317 (ねこ中尉 さん) に返信
> ClassB-1でFuncAを呼んだ場合、ClassBで改変してあるFancAを使用したいのですが、
> このような場合、どのような形で継承を行えばよろしいのでしょうか。
>
> ClassAを仮想クラスとして継承すれば、期待通りの動作が可能となるのでしょうか。

メンバ関数の呼び出しの話なので仮想クラスということではなくて、仮想関数にするか
どうかということですね。
メンバ関数をオブジェクトを通して呼び出すのであれば仮想にしなくても大丈夫ですが、
参照もしくはポインタを通して呼び出す場合は仮想関数にする必要がありますね。
(継承を使うようなケースは後者が普通だと思いますが)

> ただ、ClassA-1とClassB-1など、派生郡については、全く同じ内容で問題ないため、
> ClassA-1
> - ClassB-1
> といった継承関係も作りたいと考えています。

ClassB_1からみたとき
ClassA <-- ClassA_1 <-- ClassB_1
ClassA <-- ClassB <-- ClassB_1
と多重継承になるのですが、本当に多重継承の必然性があるかどうか、Effective C++
第3版 第6章などで検討されるのが吉かと。

#多重継承使ったことないです。。

引用返信 編集キー/
■28328 / inTopicNo.4)  Re[2]: 継承について
□投稿者/ ねこ中尉 (2回)-(2008/11/24(Mon) 16:48:25)
倉田 有大様、dogatana様、返信ありがとうございます。

■No28320 (倉田 有大 さん) に返信
> まあ、関数をオーバーライドしてやれば、インスタンスを生成した、クラスの関数がよばれますよ。
> こういう事きいてるんじゃないのかな?

以下のような形を取りたいと考えております。
class A(virtual FuncO()) → class A1()
                         → class A2()
                         → class B(FuncO()) → class B1()
                                             → class B2()

クラスBはクラスAのFunc0()を改変しているだけなので、
class B : public A
{
public:
  void Func0(){...}
}
とオーバーライドしました。

ここで、クラスB2を
class B2 : public B, public A2
{
  ...
}
と定義したいと思っています。

クラスA2のFunc0は、クラスBでオーバーライドされていないため、クラスAの定義が呼ばれます。
しかし、クラスB2では、Func0をオーバーライドしているクラスBを継承しています。

このような場合、クラスB2でFunc0を使用すると、クラスBで定義したFunc0を呼ぶことができるのでしょうか、
というのが質問意図となります。
(分かりにくくてごめんなさい)

そもそも、継承の考え方に問題があるのでしょうか・・・
クラスA群は安定した機能であるため、なるべく手を加えないで機能追加できないものかと考えているのですが。


■No28325 (dogatana さん) に返信
> メンバ関数の呼び出しの話なので仮想クラスということではなくて、仮想関数にするか
> どうかということですね。
> メンバ関数をオブジェクトを通して呼び出すのであれば仮想にしなくても大丈夫ですが、
> 参照もしくはポインタを通して呼び出す場合は仮想関数にする必要がありますね。
> (継承を使うようなケースは後者が普通だと思いますが)

>  ClassA <-- ClassA_1 <-- ClassB_1
>  ClassA <-- ClassB <-- ClassB_1
> と多重継承になるのですが、本当に多重継承の必然性があるかどうか、Effective C++
>  第3版 第6章などで検討されるのが吉かと。

クラスAにはマウスやスクロールの処理等、クラスA_1には画面出力処理が書かれています。
共通部がとても多く、継承させないと同じ修正を二つに対して行わなければならないため、
継承させたほうがいいのかな・・・といった考えでした。
プログラム設計を再検討したほうがいいのかもしれませんね。

書籍探してみます。

引用返信 編集キー/
■28341 / inTopicNo.5)  Re[3]: 継承について
□投稿者/ たくボン (71回)-(2008/11/24(Mon) 23:04:14)
No28328 (ねこ中尉 さん) に返信
> クラスAにはマウスやスクロールの処理等、クラスA_1には画面出力処理が書かれています。
> 共通部がとても多く、継承させないと同じ修正を二つに対して行わなければならないため、
> 継承させたほうがいいのかな・・・といった考えでした。
> プログラム設計を再検討したほうがいいのかもしれませんね。

うーん、共通する処理が多い場合は処理の委譲を考えてみては?ClassA群は安定しているクラス群なんですよね?
多重継承も強力だと思いますが、継承が複雑になってくると可読性を犠牲にするので。
クラス設計はシンプルなのが一番だと思います。
引用返信 編集キー/
■28342 / inTopicNo.6)  Re[3]: 継承について
□投稿者/ 倉田 有大 (363回)-(2008/11/24(Mon) 23:26:27)
> このような場合、クラスB2でFunc0を使用すると、クラスBで定義したFunc0を呼ぶことができるのでしょうか、
> というのが質問意図となります。
> (分かりにくくてごめんなさい)

とりあえず、試しにclass Aを継承した簡単なコードを書いてみて、ビルドしてみるといいですよ〜
どっちよんでいいかわからない場合は、コンパイラーが、宣言が曖昧ですみたいに、怒ってくると思います。

> そもそも、継承の考え方に問題があるのでしょうか・・・
> クラスA群は安定した機能であるため、なるべく手を加えないで機能追加できないものかと考えているのですが。

安定したクラスは、そのまま使うことをお勧めします。
でも、継承よりも
class B
{
class A;
}
みたいに、メンバ変数にもった方がいい場合もありますよ。

私もC++使っていたときは、多重継承考えてはまりました。


引用返信 編集キー/
■28343 / inTopicNo.7)  Re[4]: 継承について
□投稿者/ たくボン (72回)-(2008/11/24(Mon) 23:39:39)
No28342 (倉田 有大 さん) に返信
> 安定したクラスは、そのまま使うことをお勧めします。
> でも、継承よりも
> class B
> {
> class A;
> }
> みたいに、メンバ変数にもった方がいい場合もありますよ。

継承するってことは論理的にAとBは同階層にあるクラスだと思うので、メンバ変数に持つと意味合いが変わってくるので、処理部分を別クラスに実装してアタッチさせるのも1つの方法かも。
引用返信 編集キー/
■28344 / inTopicNo.8)  Re[4]: 継承について
□投稿者/ ねこ中尉 (3回)-(2008/11/25(Tue) 00:20:26)
たくボン様、倉田 有大様、返信ありがとうございます。

■No28341 (たくボン さん) に返信
> うーん、共通する処理が多い場合は処理の委譲を考えてみては?ClassA群は安定しているクラス群なんですよね?
> 多重継承も強力だと思いますが、継承が複雑になってくると可読性を犠牲にするので。
> クラス設計はシンプルなのが一番だと思います。

なるほど・・・委譲で考えた方がシンプルに纏まりそうです。


■No28342 (倉田 有大 さん) に返信
> 安定したクラスは、そのまま使うことをお勧めします。
> でも、継承よりも
> class B
> {
>    class A;
> }
> みたいに、メンバ変数にもった方がいい場合もありますよ。
> 
> 私もC++使っていたときは、多重継承考えてはまりました。

上記も委譲を利用すべし、といった意図となるのでしょうか。
C#では当然のように利用してた考え方なのに、C++に環境が変わったとたん混乱してしまいました。


結局、以下のような形で進めていくことにしました。
class A(virtual FuncO()) → class A1() → class B1()
                         → class A2() → class B2()
class B(Func0(){...})
class B1()
{
  B m_B;
  Func0()
  {
    m_B.Func0();
  }
}
・Aクラスのサブクラス(A1等)を継承したクラス(B1等)を作成。
・改修後共通処理をまとめたクラスBを作成。
・B1クラスなどに対し、クラスBから処理を委譲する。


以上をもちまして、解決とさせて頂きます。
返信して下さった皆様方、本当にありがとうございました。

解決済み
引用返信 編集キー/
■28345 / inTopicNo.9)  Re[2]: 継承について
□投稿者/ nori (34回)-(2008/11/25(Tue) 00:50:49)
終わってるようですが、一応

>ここで、クラスB2を
>class B2 : public B, public A2
>{
>  ...
>}
>と定義したいと思っています。
>
>クラスA2のFunc0は、クラスBでオーバーライドされていないため、クラスAの定義が呼ばれます。
>しかし、クラスB2では、Func0をオーバーライドしているクラスBを継承しています。
>
>このような場合、クラスB2でFunc0を使用すると、クラスBで定義したFunc0を呼ぶことができるのでしょうか、
>というのが質問意図となります。
>(分かりにくくてごめんなさい)
B2 b2;
b2.B::Func0()

もしくは

class B2  : public B, public A2
{
    void Func0()
    {
        B::Func0();
    }
}

ですかね。

それと、ダイヤモンド型の継承をする場合はvirtualで継承しましょう。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -