C++プログラミングのテクニック-PImpleの使用


1.Pimplコンセプト
プロジェクト開発で発生する可能性のある問題は、プログラムのコンパイルに時間がかかり、インタフェースを簡単に変更するたびにプロジェクトが完全に再コンパイルされ、多くの時間を浪費します.このメカニズムはPrivate Implementationの略で、考えを考慮して、私有化を実現し、ヘッダファイルの変化を不透明にしようとしている.コンパイル依存性の低減、再コンパイル速度の向上などのツール的な利点が多く、インタフェースの安定性を維持します.
 
2.Pimplメカニズム
Pimpl慣用法の基本思想は、既存のインタフェースclassのプライベートデータメンバーと外部から呼び出されたくない対数データメンバーの操作プロセスを1つの構造でカプセル化することであり、classのプライベートメンバーの構造は次のように見えます.
 private:
     struct Member;
     Member* data_member;
このメンバーの構造実装をcppファイルに配置すると、クラスのプライベートメンバーにはメンバー構造の順方向宣言と構造のポインタしか見えません.
これにより、ユーザーに呼び出されたくないプロセスをカプセル化し、リソースの漏洩を防ぐことができます.また、クラスとデータメンバーとの結合が最も低く、クラスは常に同じように見え、クラス宣言を含むファイルもクラス実装の変更によって再コンパイルされず、コンパイル時間を節約する.
 
既存のクラス:
 1 class Person{

 2 public:

 3    Person(void);

 4    ~Person();

 5 

 6 private:

 7    string name;

 8    size_t age;

 9    string from;

10    string work;

11 };

Pimpl慣用法修正後:
1 class Person{

2 public:

3     Person(void);

4     ~Person();

5 private:

6    struct Member;

7    Member* data_member;

8 }

メンバー関連の実装は別のcppファイルでは明らかであり,修正後Personクラスとデータメンバーの結合度が大幅に低下し,ユーザは他の詳細も見えなくなった.
 
例:
Pimplメカニズムでは、前にimplクラスを宣言し、このクラスのポインタインスタンスを次のようにメインクラスに挿入します.
//MyClass.h

class MyClassImpl;  //forward declaration

class MyClass{

public:

    MyClass();

    ~MyClass();

    int foo();

    

private:

    MyClassImpl * m_pImpl;

};

今、MyClassの共有インタフェースを変更しない限り、このヘッダファイルは変更されません.次に,このImplクラスの実装を用いて主クラスの詳細な実装を完了し,主クラスの構造関数で実装クラスポインタのインスタンス化を完了した.
 1 //MyClass.cpp

 2 class MyClassImpl{

 3 public:

 4     int foo(){return bar();}

 5     

 6     int bar(){return var++;}

 7     int var;

 8 };

 9 

10 MyClass::MyClass:m_Impl(new MyClassImpl){}

11 MyClass::~MyClass(){

12     try{

13         delete m_pImpl;

14     }

15     catch(...){}

16 }

17 

18 int MyClass::foo(){return m_pImpl->foo();}

Pimplメカニズムは実際にはブリッジモードの変種である.実装クラスは、MyClassを含むソースコードの再コンパイルを招くことなく、任意に削除および変更できます.もちろん、このような時間のオーバーヘッドや空間のオーバーヘッドもあります.