以Person類爲例,假設負責實現的那個所謂implementation class取名爲PersonImpl, Person將定義如下:
#include<string> //標準程序庫使用預編譯頭文件。
#include<memory> //爲了智能指針tr1::shared_ptr而含入
class PersonImpl; //Person實現類的前置聲明
class Date; //Person接口用到的class的前置聲明
class Address;
class Person{
public:
Person(const std::string& name,const Date& birtthday,const Address& addr);
std::string name() const;
std::string birthDate() const;
std::string address() const;
private:
std::tr1::shared_ptr<PersonImpl> pImpl; //指針,指向實現物;
}
下面是Person類的兩個成員函數的實現:
#include "Person.h" //這裏需要包含Person class定義式。
#include "PersonImpl.h" //也必須包含PersonImpl class定義式。
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;
}
在上方成員函數實現中,Person構造函數以new調用PersonImpl構造函數,
在Person::name()函數內調用PersonImpl::name。這種設計方法就將類的聲明和實現相分離,從而最大化的減小了編譯依存關係。
對於Handle classess這種方法,成員函數必須通過指針實現取得對象數據。這種形式會爲每一次訪問增加一層間接性。
而每一個對象消耗的內存數量必須增加實現指針PersonImpl的大小。並且,這個實現指針PersonImpl必須在Handle classe構造函數內初始化,並指向一個動態分配得來的實現對象。所以這種操作方法要將蒙受因動態內存分配而帶來的額外開銷以及bad_alloc異常(內存不足)的可能性。
方法二:令Person成爲一個特殊的抽象基類。稱爲Interface class。
這種類的目的是詳細描述派生類的接口,因此它通常不帶成員變量,也沒有構造函數,只有一個虛析構函數以及一組純虛函數,用來敘述整個接口。
Interface class爲這種class創建新對象會採用工廠函數或虛構造函數來實現。這些函數返回指針(通常爲智能指針),
指向動態分配所得的對象,而該對象支持Interface class的接口。這樣的函數往往在Interface class內被聲明爲static。
實現代碼如下:
class Person{
public:
virtual ~Person();
virtual std::string name() const = 0;
virtual std::string birthDate() const = 0;
virtual std::string address() const = 0;
static std::tr1::shared_ptr<Person> //返回一個tr1::shared_ptr,指向一個新的Person,並以給定之參數初始化。
create(const std::string& name,
const Date& birthday,
const Address& addr);
};
可以這樣使用它們:、
std::string name;
Date dateOfBirth;
Address address;
//創建一個對象,支持Person接口。
std::tr1::shared_ptr<Person> pp(Person::create(name,dateOfBirth,address));
std::cout<<pp->name()<<pp->birthDate()<<pp->address();
實現Interface class有兩個常見機制,這裏採用的是從Interface class(Person)繼承接口規格,然後實現出接口所覆蓋的函數。
當然,支持Interface class接口的那個具象類必須被定義出來,而且真正的構造函數必須被調用。
假設Interface class Person有個具象的派生類 RealPerson,後者提供繼承而來的虛函數的實現:
class RealPerson: public Person{
public:
RealPerson(const std::string& name, const Date& birthday, const Address& addr)
: theName(name), theBirthDate(birthday),theAddress(addr)
{}
virtual ~Person();
virtual std::string name() const = 0;
virtual std::string birthDate() const = 0;
virtual std::string address() const = 0;
private:
std::string theName;
Date theBirthDate;
Address theAddress;
};
有了RealPerson之後,寫出Person::create的實現代碼:
Person::create(const std::string& name, const Date& birthday, const Address& addr)
{
return std::tr1::shared_ptr<Person>(new RealPerson(name,birthday,addr));
}