C++の多態
# 今日からソフト屋モード。
C++の多態は大まかに2系統の表現方法があります。
一つはJavaや.NET等と同じ所謂"オブジェクト指向"な仕組み(継承とvtblによる動的な多態)、
もう一つはC++特有のtemplateによる静的な多態です。
今日は(続くかどうかわからない)C++シリーズの第一弾として、C++(に限らず)継承を使うときの有名なセオリーを軽く紹介します。
リスコフの代入則
public継承を使う場合は、"派生クラスを親クラスとして扱っても不都合が生じない"ように設計しなければならない。
例えば、テキストボックス(==入力と表示が一致している)を実装しているクラスをpublic継承して、入力が自動的に大文字に変換されるテキストボックス(==入力と表示が一致しない)を実装してはいけない。
この場合は、テキストボックスをフィールドとして持ち(合成,composition)、転送関数を並べて実装するか、入力そのものをフックしなければならない。
private継承を使う場合は、使う前にそれが合成では実現できないかをよく吟味する。private継承が必要な典型的な例は、protectedメンバにアクセスする必要がある場合と、empty-base optimizationが有効な場合。
NVI(Non Virtual Interface)イディオム
派生クラスにオーバーライドさせるメソッドは、public non-virtualの転送関数から呼ばれるprotected virtualメソッドにせよ。
class base { public: int some_interface() { return do_some_action(); } protected: virtual int do_some_action(); public: virtual ~base(); }; class derived: public base { private: int do_some_action(); };
仮想関数は非公開でも問題なくオーバーライド可能ですし、計測コード等を埋め込みやすいという利点もあります。
親クラスの振る舞いをなぞりたいなら、通常通り
int derived::do_some_action() { return base::do_some_action(); }
してしまえばOKです。