以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));
}