Skip to content

Instantly share code, notes, and snippets.

@torus
Created August 5, 2009 03:09
Show Gist options
  • Save torus/162469 to your computer and use it in GitHub Desktop.
Save torus/162469 to your computer and use it in GitHub Desktop.
=<center>ハンドル・ボディ(Handle Body)</center>=
=== 意図 ===
* 実装からインターフェイスを分離する
* 実装の詳細が変更されても、そのクラスの使用者に影響がないように(再コンパイルを不要に)する
=== Also Known As ===
* [[More C%2B%2B Idioms/ハンドル・ボディ(Handle Body)|Bridge]] (Gamma et al.)
* [[More C%2B%2B Idioms/ハンドル・ボディ(Handle Body)|Compilation Firewall]]
* [[More C%2B%2B Idioms/ハンドル・ボディ(Handle Body)|Cheshire Cat]]
* [[More C%2B%2B Idioms/ハンドル・ボディ(Handle Body)|PImpl (Pointer to Implementation) idiom]]
=== 動機 ===
C++ ではクラスは実装を定義するとともにインターフェイスを宣言することにも使われる。
プライベートメンバ関数は、クラスの「インターフェイス」ではないにもかかわらず、クラス利用者に見えるようにクラスの中で宣言しなくてはいけない。
プライベートデータメンバの宣言やプライベート関数のシグネチャを変更すると、利用者のコードも再コンパイルしなくてはいけなくなる。
したがって、クラスの実装からインターフェイスを分離し、不必要な再コンパイルを防ぐのは有用である。
=== 解法とサンプルコード ===
abstractionを2つの実装クラスに分離する。
ひとつは識別子としての役割をし、利用者に対してクラスインターフェイスとなる。
これは''ハンドル''と呼ばれる。
他方のクラスは、実装を具体化し、''ボディ''と呼ばれる。
ハンドルはメンバ関数の実行をボディにフォワードする。
Split an abstraction into two implementation classes. One takes on the role of an identifier and presents the class interface to the user. It is called the ''handle''. The other class embodies the implementation and is called the ''body''. The handle forwards member function invocations to the body.
<source lang="cpp">
// 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
</source>
これにより、実装(ボディ)に対して安全にデータの変更を行うことができ、ハンドルの利用者は再コンパイルの必要がない。
実装はポインタの影に「より隠される」ので、コンパイルファイアウォールとも呼ばれる。
Data changes can now safely be made to the implementation (body) without recompiling clients of the handle. The implementation becomes "more hidden" behind a pointer, hence the name: Compilation Firewall.
=== consequence ===
* The extra level of indirection has a performance cost.
* ひとつ回り道をするのでコストがかかる。
* This idiom doesn't address the issues of deep versus shallow copy and other runtime dynamics; See [[More C++ Idioms/Counted Body|Counted Body]], [[More C++ Idioms/Envelope Letter|Envelope Letter]].
* このイディオムはディープコピーやシャロウコピー、あるいはそのほかの実行時の動作には関知しない。[[More C++ Idioms/Counted Body|Counted Body]]、[[More C++ Idioms/Envelope Letter|Envelope Letter]]を参照のこと。
* The idiom also makes inheritance less useful. See [[More C++ Idioms/Handle Body Hierarchy|Handle Body Hierarchy]] to overcome this shortcoming.
* このイディオムを使うと継承があまり役に立たなくなる。この欠点を補うには[[More C++ Idioms/Handle Body Hierarchy|Handle Body Hierarchy]]を参照のこと。
* This idiom has limits in managing the dynamically allocated memory of the body class; see [[More C++ Idioms/Counted Body|Counted Body]].
* このクラスはボディの動的なメモリ確保に制限がある。[[More C++ Idioms/Counted Body|Counted Body]]を参照。
* It also introduces the need for occasional redundant update to the handle and body classes, a problem addressed in part by [[More C++ Idioms/Envelope Letter|Envelope Letter]] and [[More C++ Idioms/Smart Pointer|Smart Pointer]].
=== Known Uses ===
* Vast majority of non-trivial C++ software!
=== Related Idioms ===
* [[More C++ Idioms/Counted Body|Counted Body]]
* [[More C++ Idioms/Smart Pointer|Smart Pointer]]
* [[More C++ Idioms/Envelope Letter|Envelope Letter]]
* [[More C++ Idioms/Handle Body Hierarchy|Handle Body Hierarchy]]
* [[More C++ Idioms/Checked delete|Checked delete]]
* [[More C++ Idioms/Fast Pimpl|Fast Pimpl]]
=== References ===
* http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#HandleBody
* [http://www.ddj.com/cpp/205918714 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).
[[Category:{{BASEPAGENAME}}|{{SUBPAGENAME}}]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment