More C++ Idioms/ハンドル・ボディ(Handle Body)
ハンドル・ボディ(Handle Body)
編集
意図
編集- 実装からインターフェイスを分離する
- 実装の詳細が変更されても、そのクラスの使用者に影響がないように(再コンパイルを不要に)する
別名
編集- Bridge (Gamma et al.)
- コンパイル防壁(Compilation Firewall)
- チェシャ猫(Cheshire Cat)
- PImpl (Pointer to Implementation) idiom
動機
編集C++ ではクラスは実装を定義するとともにインターフェイスを宣言することにも使われる。 プライベートメンバ関数は、クラスの「インターフェイス」ではないにもかかわらず、クラス利用者に見えるようにクラスの中で宣言しなくてはいけない。 プライベートデータメンバの宣言やプライベート関数のシグネチャを変更すると、利用者のコードも再コンパイルしなくてはいけなくなる。 したがって、クラスの実装からインターフェイスを分離し、不必要な再コンパイルを防ぐのは有用である。
解法とサンプルコード
編集abstractionを2つの実装クラスに分離する。 ひとつは識別子としての役割をし、利用者に対してクラスインターフェイスとなる。 これはハンドルと呼ばれる。 他方のクラスは、実装を具体化し、ボディと呼ばれる。 ハンドルはメンバ関数の実行をボディにフォワードする。
// String.hppファイル
class StringRep; // 前方宣言のみ
class String {
public:
String();
String(const String &s);
String &operator=(const String &s);
~String();
String(const char *s);
. . . .
private:
StringRep *rep; // ポインタで実装する (pimpl)
};
// String.hppファイル ここまで
// String.cppファイル
#include "String.hpp"
namespace { // 無名名前空間
class StringRep {
// このクラスの定義はクライアントからは見えないようにし、
// Stringクラスとは別々のソースファイルとしてコンパイルされるべき。
friend class String;
StringRep(const char *s);
~StringRep();
int count; char *rep;
};
} // 無名名前空間終わり
String::String() // コンストラクタや、その他諸々の定義
. . . .
これにより、実装(ボディ)に対して安全にデータの変更を行うことができ、ハンドルの利用者は再コンパイルの必要がない。 実装はポインタの影に「より隠される」ので、コンパイルファイアウォールとも呼ばれる。
問題点
編集- ひとつ回り道をするのでコストがかかる。
- このイディオムはディープコピーやシャロウコピー、あるいはそのほかの実行時の動作には関知しない。計数ボディ(Counted Body)、封筒・便箋(Envelope Letter)を参照のこと。
- このイディオムを使うと継承があまり役に立たなくなる。この欠点を補うにはHandle Body Hierarchyを参照のこと。
- このクラスはボディの動的なメモリ確保に制限がある。計数ボディ(Counted Body)を参照。
- また、まれに、封筒・便箋(Envelope Letter)やスマートポインタ(Smart Pointer)で述べられているハンドルとボディの冗長な更新の必要が生じる。
既知の利用
編集- 単純でないC++ソフトウェアでは広く用いられている!
関連するイディオム
編集- 計数ボディ(Counted Body)
- スマートポインタ(Smart Pointer)
- 封筒・便箋(Envelope Letter)
- Handle Body Hierarchy
- チェック付きdelete(Checked delete)
- 高速 Pimpl(Fast Pimpl)
References
編集- http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#HandleBody
- Making Pimpl Easy -- Vladimir Batov
Copyright
編集Original copyright ©1998 Lucent Technologies, Bell Labs Innovations. All rights reserved. Permission granted to reprint verbatim for non-commercial use provided this copyright notice appears. (Contents edited for Wikibooks).