Effective C++Item 31ファイル間コンパイル依存関係を下げる.

3098 ワード

この記事はsenlieオリジナルです.転載はこの住所を残してください.http://blog.csdn.net/zhengsenlie
経験:「コンパイル依存性最小化」の一般的な構想は、ステートメントに依存して定義式に依存しないことです.この構想に基づく2つの手段は、Handle clasesとInterface clasesです.例:定義式に依存します.
#include <string>
#include "date.h"
#include "address.h"
class Person{
public:
	Person(const std::string &name, const Data &birthday, const Address &addr);
	std::string name() const;
	std::string birthDate() const;
	std::string address() const;
	//...
private:
	std::string theName; //    
	Date theBirthDate;   //     
	Address theAddress;  //    
}
解析:
一旦includeのファイルが変更されたら、Person classを使用するファイルは再度リンクをコンパイルしなければなりません.
訂正:ステートメントに依存します.pointer to implementは、インターフェースと分離を実現します.
#include <string>
#include <memory>


class PersonImpl;  //Person  
class Date;
class Address;


class Person{ //Person   
public:
	Person(const std::string &name, const Date &birthday, const Address &addr);
	std::string name() const;
	std::string birthDate() const;
	std:;string address() const;
	//...
private:
	std::tr1::shared_ptr<PersonImpl> pImpl; //  ,     ;
}
解析:
1.object referencesまたはobject pointersを使用すれば、タスクを完了することができます.objectを使用しないでください.
指向型のreferencesとpointersを定義するには、タイプ宣言が必要です.
定義タイプのobject-->はタイプ定義式が必要です.
2.できれば、クラスの定義式をできるだけclass宣言式に置き換える.
#include "datefwd.h" //        (    )class Date
Date today(); //ok.    Date     
void clearAppointment(Date d); //ok.     Date    
void clearAppointment(Date d){} //error. imcomplete type is not allowed.
3.ステートメント式と定義式のために異なるヘッダファイルを提供します.「本当に必要なタイプの定義ではない」とクライアント間のコンパイル依存性を取り除くことができます.
例えば、「iosfwd」には、iostreamの各コンポーネントの宣言式が含まれています.その対応する定義は、異なるヘッダファイルに基づいて、「sstream」を含みます.
<stream>、<fstream>と<iostream>
Personのようなhandle clasesを実現します.
方法の1:それらのすべての関数を対応する実現クラスに渡して、後者によって実際の仕事を完成させます.
#include "Person.h"
#include "PersonImpl.h" //   Person class    include Person   PersonImpl     。
						//?     include PersonImpl.cpp,            
Person::Person(const std::string &name, const Date &birthday, const Address &addr)
	:pImpl(new PersonImpl(name, birthday, addr)
{};
std::string Person::name() const {
	return pImpl->name();
}
方法2:Interface class.インターフェースの仕様をInterface classから引き継ぎ、インターフェースがカバーする関数を実現します.
class Person{
public:
	
	static std::tr1::shared_ptr<Person> //    tr1::shared_ptr,      person,Item 18              
		create(const std::string &name, const Date &birthday, const Address &addr);
	virtual ~Person();
	virtual std::string name() const = 0;
	virtual std::string birthDate() const = 0;
	virtual std::string address() const = 0;
	//...
};


class RealPerson: public Person{
	//...
}


std::tr1::shared_ptr<Person> Person::create(const std::string &name,
											const Date &birthday,
											const Address &addr)
{
	return std::tr1::shared_ptr<Person>(new RealPerson(name, birthday, addr));
}