読者です 読者をやめる 読者になる 読者になる

ぷろみん

プログラミング的な内容を扱ってます

コンパイラファイアウォール

概要

依存関係を減らしコンパイル時間を減らすという考え方です。

手法

  • インターフェース
  • 前方宣言
  • 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();
};

外部が必要の無いデータにより依存関係が増えるのはいかにも面白くないです。
有名なパターンなので詳しい解説はしません。

アンチパターンとしても聞くのですが、これより良い データ隠蔽手法って何があるんですかね?