34項 コンパイルするファイル間の依存性はできるだけ減らそう
コンパイルするファイル間の依存性はできるだけ減らそう
多くincludeされているヘッダファイルの実装が変更されると、そのヘッダファイルを一度でもincludeしたファイルの再コンパイルを行うことになってしまいます。
本書の例を引用します。
#include <string> #include "date.h" #include "address.h" #include "country.h" class Person { public: Person(const string &name, const Date &birthday, const Address &addr, const Country &country); ~Person(); ... string name() const ; string birthDate() const ; string address() const ; string nationality() const ; private: string name_; Date birthDate_; Address address_; Country citizenship_;
Personクラスはname_,birthDate_,address_,citizenship_とクラスの実態を含んでいます。
もしこの4つのクラスの、いずれかの実装が変更された場合、Personクラスを使うすべてのファイルの再コンパイルが必要になります。
これを解決するためには、Personクラスの定義と、Personクラスに含まれるクラスの実装を切り離す必要があります。
本書では、以下のように切り離しています。
//先行宣言 class string; class Date; class Address; class Country; class PersonImpl; class Person { public: Person(const string &name, const Date &birthday, const Address &addr, const Country &country); ~Person(); ... string name() const ; string birthDate() const ; string address() const ; string nationality() const ; pribate: PersonImpl *impl;
Personの実装は以下のようにします。
#include "Person.h" #include "PersonImpl.h" Person::Person(const string &name, const Date &birthday, const Address &addr, const Country &country); { impl = new PersonImpl(name, birthday, addr, country); } string Person::name() const { return impl->name(); }
このように実装することで、string,Date,Address,Countryのいずれかのクラスの実装が変更されても、PersonImplの実装のみの再コンパイルにとどめられます。
本書には、切り離すときの3つの方針が挙げられています。
・オブジェクトのリファレンスやポインタで間に合うときは、オブジェクトを使わない。
・クラス宣言を使えるときは、クラス定義を使わない。
・あなたのヘッダファイルは、コンパイルに必要なものを除いて、ほかのヘッダファイルを#includeしてはならない。