Effective C++読書メモ #35

2015年10月8日木曜日

Item 35: Consider alternatives to virtual functions
前回: Effective C++読書メモ #34
前回はインタフェースの継承と実装の継承をうまく使い分けるという話だった。
今回はvirtual関数の代替策を考えるという話。前回と関連したもの。

Non-Virtual Interface(NVI)を使ったTemplate Methodパターン

virtual関数はほとんどの場合でprivateにすべきという議論があり、それに従うと外部からのアクセス用メソッドをpublicで作成して内部でprivate virtualな実体を呼び出す方法がある。
処理実体の前後に特定の処理(ロギングなど)を挟み込みたい場合に便利。
これをvon-virtual interface(NVI)イディオムと呼び、デザインパターン方面ではテンプレートメソッドと呼ばれるもの。ここでのテンプレートはC++のテンプレートとは関係ないよというのが書かれている。

関数ポインタを使ったStrategyパターン

そもそも処理実体がクラス内に存在する必要がない場合にはNVIイディオムはあまりマッチしない。そういう場合にはコンストラクタに計算用関数のポインタを渡すなどして外部のものを使う方法がある。
この場合は計算ロジックを実行時に選択できるし、同クラスの別インスタンス同士で異なる計算ロジックを利用できる。
一方で計算ロジックが元クラス外にあるということは元クラスのpublic要素にしかアクセスできなくなる問題がある。原則的にこれはクラスのカプセル化をゆるめることで解決するしかない。

tr1::functionを使ったStrategyパターン

さきの関数ポインタによる実装に柔軟性を持たせられるのがtr::functionを使うパターン。
関数の代わりに関数オブジェクトを使ったり、指定型の戻り値の代わりにその型へ変換できる任意の型を使ったり、という便利さを得られる。
[*1] Scott Meyers自身による説明がhttp://www.aristeia.com/EC3E/TR1_info.htmlにある。

クラシックなStrategyパターン

計算用クラスのツリーを作っていき、そのポインタを計算利用側に持つという伝統的なやつ。計算種類を増やしたくなったら計算用クラスを継承して新規作成すればいい。

結果

いろいろな方法が考えられるということはおさえておこうねというのが論旨、という話でおしまい。

0 件のコメント:

コメントを投稿