ヘッダーで実装の詳細を公開することには利点があるだけでなく、詳細が変更されたときに強制的に再コンパイルするという欠点があることに注意してください。関数をより簡単にインライン化できるため、実行時のパフォーマンスが向上します。そのトレードオフがコストに見合う場所と時期を決定する必要があります。
追加レベルの間接参照を導入することにより、ソースファイル内のすべてのプライベート実装の詳細を非表示にすることができます。一般的なアプローチの1つは、プライベート実装(または「pimpl」)へのポインタのイディオムです。次に例を示します。
// Header file
class Thing {
public:
Thing(...);
~Thing();
// Public interface
private:
struct Impl;
std::unique_ptr<Impl> impl;
};
// Source file
struct Thing::Impl {
// private details
};
Thing(...) : impl(new Impl(...)) {}
~Thing() {}
// Implementation of public interface
もう1つの可能性は、実装を含む具体的なインスタンスを作成するための1つ以上のファクトリを使用して、抽象インターフェイスを定義することです。次に例を示します。
// Header file
class Thing {
public:
virtual ~Thing() {}
static std::unique_ptr<Thing> make(...);
// Pure virtual public interface
};
// Source file
class ThingImpl : public Thing {
// Implementation of public interface
// Private implementation details
};
std::unique_ptr<Thing> Thing::make(...) {
return std::unique_ptr<Thing>(new ThingImpl(...));
}
これらのアプローチはどちらも、すべての実装の詳細をソースファイル内に配置するため、詳細が変更されたときに再コンパイルする必要があるのはそれだけです。ただし、どちらも追加のポインター間接参照や間接関数呼び出しを導入し、実行時のパフォーマンスに影響を与える可能性があります。