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

これにより、実装(ボディ)に対して安全にデータの変更を行うことができ、ハンドルの利用者は再コンパイルの必要がない。 実装はポインタの影に「より隠される」ので、コンパイルファイアウォールとも呼ばれる。

[編集] 問題点

[編集] 既知の利用

  • 単純でないC++ソフトウェアでは広く用いられている!

[編集] 関連するイディオム

[編集] References

[編集] 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).

ヘルプ
他の言語