【c++】激震が走った、Pimplイディオム


元ブログ 【c++】激震が走った、Pimplイディオム - 技術は熱いうちに打て!

今日C++のためのAPIデザイン
を読んでいて、激震が走りました。

C++では嫌でもprivateな変数や関数も.hファイルに宣言する必要がある。

そう思っていた時期が僕にもありました。

でも、違うんです。

どうやらPimplと言うイディオムを使うとcppファイルに隠蔽出来るそうです。

Pimpl導入前のコード

簡単な例で示してみましょう。
ここにHogeと言うクラスがあり、インスタンス化されたらhogeと出力されるクラスがあります。

Hoge.h
// Hoge.h
class Hoge
{
public:
    Hoge();
    ~Hoge();

private:
    void printHoge();
};
Hoge.cpp
#include "Hoge.h"

Hoge::Hoge()
{
    this->printHoge();
}

Hoge::~Hoge() {}

void Hoge::printHoge()
{
    CCLOG("hoge");
}

Pimpl導入後のコード

Hoge.h
class Hoge
{
public:
    Hoge();
    ~Hoge();

private:
    class Impl;
    std::unique_ptr<Impl> hoge;   ...
};
Hoge.cpp
#include "Hoge.h"

class Hoge::Impl
{
public:
    void printHoge();
};                                ...

Hoge::Hoge()
    : hoge(new Hoge::Impl())      ...
{
    this->hoge->printHoge();      ...
}

Hoge::~Hoge() {}

void Hoge::Impl::printHoge()      ...
{
    CCLOG("hoge");
}

解説

導入後のコードを見て下さい。
注釈しているところが主な変更点です。

ヘッダファイル

...Ⅰ
まず、privateでclass宣言します。
名前はなんでも良いと思います。
Hogeクラスでprivateに行いたい動作を記述するクラス名となります。
ヘッダファイルではこのクラスのインスタンスを宣言するところまでを記述。

実装ファイル

...Ⅱ
- 新しいクラスのインターフェースを宣言します。
publicにしないとHogeクラス内からでも使えないので注意。

...Ⅲ
- 新しいクラスをコンストラクタでインスタンス化します。

...Ⅳ
- 新しいクラスのインスタンスを通じてメソッドを呼び出します。

...Ⅴ
- もともとHogeクラスでprivateで行いたかった実装をここに書きます。

あとがき

これはかなりの衝撃でしたね。
僕はObjective-CからC++に来ました。
Objective-Cではヘッダに書かずに.mファイルに直接実装すればprivateな関数になっていたのですが、C++ではヘッダファイルに宣言のみ書かなければいけないと言う制約。
でもこのPimplでそのストレスからも解放されそうです。

誰かのお役に立てば。
これは立つでしょう!!