經驗:支援”編譯依存性最小化“的一般構想是:相依于聲明式,不要相依于定義式。
基于此構想的兩個手段是 Handle classes 和 Interface classes.
示例:相依于定義式
[cpp] view plain copy
- #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 implementation,接口與實作分離
[cpp] view plain copy
- #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 可以完成任務,就不要使用 objects。
定義指向類型的references 和 pointers --> 需要類型聲明式
定義類型的 object --> 需要類型定義式
2.如果能夠,盡量以 class 聲明式替換 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>,
<streambuf>,<fstream>和<iostream>
實作類似 Person 這類 handle classes
方法之一: 将它們所有函數轉交給相應的實作類并由後者完成實際工作。
[cpp] view plain copy
- #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();
- }
方法二:Interface class。從 Interface class 繼承接口規格,然後實作出接口所覆寫的函數。
[cpp] view plain copy
- 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));
- }