コンパイラファイアウォール
概要
依存関係を減らしコンパイル時間を減らすという考え方です。
手法
- インターフェース
- 前方宣言
- PImpl
インターフェース
インターフェースを継承した様々なクラスを知らずに使えます。
// foo.h struct Foo{ virtual void Func() = 0; virtual ~Foo(){} }; Foo* NewFoo();
// foo.cpp struct Bar : public Foo{ void Func(){} }; Foo* NewFoo(){ return new Bar; }
// main.cpp #include "foo.h" int main(){ auto a = NewFoo(); // barを知らないのにbarが使えた a->Func(); delete a; }
前方宣言
前方宣言があればインターフェイスすら知らなくても良くなります。
// foo.h // Fooの前方宣言 struct Foo; Foo* NewFoo(); void Func(Foo*);
// foo.cpp // FooとBarとNewFooの実装 void Func(Foo* a){ a->Func(); }
#include "foo.h" int main(){ auto a = NewFoo(); // Fooの実装すら知らないのにbarが使えた Func(a); delete a; }
注意点としては何でもかんでも前方宣言にしてしまうと駄目って事です。
ヘッダーは単体で完結している事が求められます。
せっかくの機能が不完全クラスですと言われると残念な設計になってしまいます。
PImpl
class Foo{ // データメンバを隠蔽 class Impl; Impl* pimpl; public: Foo(); ~Foo(); void Func(); };
外部が必要の無いデータにより依存関係が増えるのはいかにも面白くないです。
有名なパターンなので詳しい解説はしません。
アンチパターンとしても聞くのですが、これより良い データ隠蔽手法って何があるんですかね?