More C++ Idioms/ハンドル・ボディ(Handle Body)
出典: フリー教科書『ウィキブックス(Wikibooks)』
目次 |
[編集]
ハンドル・ボディ(Handle Body)
[編集] 意図
- 実装からインターフェイスを分離する
- 実装の詳細が変更されても、そのクラスの使用者に影響がないように(再コンパイルを不要に)する
[編集] 別名
- Bridge (Gamma et al.)
- コンパイル防壁(Compilation Firewall)
- チェシャ猫(Cheshire Cat)
- PImpl (Pointer to Implementation) idiom
[編集] 動機
C++ ではクラスは実装を定義するとともにインターフェイスを宣言することにも使われる。 プライベートメンバ関数は、クラスの「インターフェイス」ではないにもかかわらず、クラス利用者に見えるようにクラスの中で宣言しなくてはいけない。 プライベートデータメンバの宣言やプライベート関数のシグネチャを変更すると、利用者のコードも再コンパイルしなくてはいけなくなる。 したがって、クラスの実装からインターフェイスを分離し、不必要な再コンパイルを防ぐのは有用である。
[編集] 解法とサンプルコード
abstractionを2つの実装クラスに分離する。 ひとつは識別子としての役割をし、利用者に対してクラスインターフェイスとなる。 これはハンドルと呼ばれる。 他方のクラスは、実装を具体化し、ボディと呼ばれる。 ハンドルはメンバ関数の実行をボディにフォワードする。
// file String.hpp class StringRep; // Forward declaration only. class String { public: String(); String(const String &s); String &operator=(const String &s); ~String(); String(const char *s); . . . . private: StringRep *rep; // Pointer to implementation (pimpl) }; // file String.hpp ends here // file String.cpp #include "String.hpp" namespace { // Anonymous namespace class StringRep { // This should be in a separate source file than class String, so it can be compiled // separately, and made invisible to the client friend class String; StringRep(const char *s); ~StringRep(); int count; char *rep; }; } // anonymous namespace ends String::String() // constructors and everything else
これにより、実装(ボディ)に対して安全にデータの変更を行うことができ、ハンドルの利用者は再コンパイルの必要がない。 実装はポインタの影に「より隠される」ので、コンパイルファイアウォールとも呼ばれる。
[編集] 問題点
- ひとつ回り道をするのでコストがかかる。
- このイディオムはディープコピーやシャロウコピー、あるいはそのほかの実行時の動作には関知しない。計数ボディ(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).