Pimpl
“Pimpl” == “pointer to implementation” == “Compilation Firewalls” == “Cheshire Cat”
Pimpl 是一個隱藏實作的技術,用於 C++ 或其他類似的 statically compiled languages。 做法是把實作的東西包成一個 class,在 header 檔只宣告這個 class, 而 class 內部有什麼則是另外再實作, 所以 header 檔裡面看到的會是對外的一些 interface 以及只有宣告的實作細節。
範例 code :
// widget.hpp
#include <memory>
class widget {
public:
widget();
~widget();
private:
class impl;
std::unique_ptr<impl> pimpl;
};
////////////////////////////////////////
// widget.cpp
#include "widget.hpp"
class widget::impl {
// implementation
};
widget::widget() : pimpl{ std::make_unique<impl>() } { }
widget::~widget() = default;
優點:
更改實作時,用到這實作的 code 不用重新編譯
缺點:
實作者需要多做一些事
因為是間接的處理,所以執行期間的效能會稍稍的下降,尤其是 function calls 是 virtual 時,branch prediction 對於 indirect branches 通常效能會比較差
code 可能比較難讀,因為一些資訊不在 header 檔裡面
要點:
Pimpl object 應該要不能 shared,所以使用 unique_ptr (也比 shared_ptr 有效率)
在自己的實作裡面使用 Pimpl object,這樣可以把實作細節藏起來
在 out-of-line constructor 建立 Pimpl object
在自己實作裡仍需要寫 destructor,如此一來才會讓 compiler 在已經定義完實作 class 的地方建立 destructor,而不是讓 compiler 在原本的 header 檔那裡嘗試用不完整的型別建立 destructor
如果需要 copy & move assignment 的話,也需要在實作檔案裡寫上
Pimpl 這種型別是非常 move-friendly 的,因為只需要 copy 一個 pointer 值
根據設計上來說,private 和 nonvirtual members 為 implementation details,只有這塊需要被 Pimpl 藏起來