\n |
[ トップページ ]
[ ____CommandPrompt ]
[ ____JScript ]
[ ____MySQL ]
[ ____Cygwin ]
[ ____Java ]
[ ____Emacs ]
[ ____Make ]
[ ____Perl ]
[ ____Python ]
[ ____OpenGL ]
[ ____C# ]
[ ____StyleSheet ]
[ ____C++ ]
[ ____Winsock ]
[ ____Thread ]
[ ____VisualStudio ]
[ ____C ]
[ ____Win32API ]
[ ____Lua ]
[ ____PhotoShop ]
ヘッダ検索
■ 継承(inheritance)
■ public.継承
public 継承した場合は 基底クラスへのキャストは安全にできる。
基底クラスの実装内容を再利用して、拡張したクラスを作るには public 継承を使う。
class Gui {
};
class Button : public Gui {
};
] ]]
■ 正しく継承する
より少ない要件で、より多くの振る舞いをすることが正しい。
こうすることで、既存のシステムに新しいものを追加しても破壊されない。
逆に仕様を満たせば、中身は基底クラスと同じでなくてもよい。
■ 実装の継承とインターフェイスの継承
継承は2種類ある。
実装の継承とは クラスの属性、メソッドを基底クラスにまとめてしまうこと。
同じコードがあったときに、関数としてまとめるのと同じ。
複数のクラスに同じような、属性、メソッドがあればそれらをまとめて重複を減らす。
class Gui {
// 大きさ、位置などのパラメータはどの Gui ももっているのでまとめる。
float x, y;
float szx, szy;
// メソッドも共通化できる。
void setPosition( float x, float y );
};
// スライダ固有のパラメータのみを追加する
class Slider : public Gui {
};
インターフェイスの継承は実装を基底クラスからもらうわけではなく
呼び出し方法のみを継承する。
こうしておくと
呼び出し( システム )側が、各インスタンスのクラスごとに場合わけをする必要がなくなる
またインターフェイスだけを知ればよくなるので、実装側のクラスのヘッダが不要になる。
知るべきことが減る。
カプセル化といって、知らなくてもいいことを知らないようにしておくことができる。
class Gui {
virtual void onClick() = 0;
};
class Button : public Gui {
void onClick() {
}
};
■ 継承の使いどころ
if - else で似たようなコードがあったら継承の使いどころ
継承はクラスをグループ化する。
window_event_callback( msg, type ) {
if ( type == E_BUTTON ) {
button->onClick( msg );
}
if ( type == E_BUTTON ) {
text->onClick( msg );
}
if ( type == E_BUTTON ) {
menu->onClick( msg );
}
}
同じようなコードがあるので、基底クラスで仕様だけを決めてしまう。
Gui であるすべてのクラスは onClick( msg ) をもっているというルールをつくる。
class Gui {
virtual void onClick( int msg ) = 0;
};
派生クラスで具体的な処理を仕様にそってつくる。
Button は Gui の一種である。
class Button : public Gui {
void onClick( int msg ) {
}
};
システム側はまとめることができる。クラスごとに場合わけをせずに
基底クラスのインターフェイスにだけアクセスすればよくなる。
window_event_callback( msg, type ) {
gui->onClick( msg );
}
基底クラスの Gui を作る必要がなければ メソッドを = 0 としてしまう。
こうすると
基底クラスで仕様だけを決めるときは、 間違って実体化できないようにしておく。
もし空の実装を用意しておくと、間違ってオーバーライドの忘れなどが発生してしまう。
そこで = 0 として中身がないことをコンパイラに教えて実装忘れがあった場合に怒ってもらう
class Gui {
virtual void onClick( int msg ){}
};
REFERENCE 純粋仮想関数
インスタンスをつくれなくなる。
■ 関数のオーバーロード
派生先で同名のメンバ関数をつくると, オーバーライドはされずに基底クラスの関数が隠される。
そのため 派生先では同名の関数をつくらないようにする。
class Base {
public:
void display();
};
class Derive {
public:
// これは基底の display() を隠す。
void display();
};
Derive d;
func( d, d );
void func( Base &b, Derive &d ) {
// Base::display() が呼ばれる。
b.display();
d.display();
}
■ private継承
private 継承をすると基底クラスの public, protected が 派生クラスの private になる。
protected継承をすると同様に, protected となる。
いつも利用している public 継承は, 基底クラスの public は派生クラスの public になる。
POINT
使いどころは protected アクセスを追加したいとき
また 基底クラスへのポインタに変換できる。
|
|
NINJAIDX 12