#include
#include "date.h"
#include "address.h"
class 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::string theName; // 实现细节
Date theBirthDate; // 实现细节
Address theAddress; // 实现细节
};
如果这些头文件发生了任何变化,或者它们依赖的任何头文件发生了变化,则必须重新编译所有包含Person类的文件。
为什么不能这样定义Person,单独指定类的实现细节呢:
namespace std {
class string; // 前置声明(不正确)
}
class Date; // 前置声明
class Address; // 前置声明
class 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;
...
};
int main()
{
int x; // 定义一个int(内置类型大小是明确的)
Person p(params); // 定义一个Person(需要通过数据成员的大小,计算所需内存)
Person *p2; // 定义一个指向Person对象的指针(指针也是内置类型)
...
}
主要原因有下:
可以采用pimpl (pointer to implemention)方法,“将对象实现细节隐藏在指针背后”
#include // 标准库组件不应该前置声明
#include // std::shared_ptr
class PersonImpl; // Person 实现类的前置声明
class Date; // Person接口中使用的类型的前置声明
class Address;
class 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::shared_ptr<PersonImpl> pImpl; // 指向实现的对象
};
#include "datefwd.h" // 声明(但不定义)Date类的头文件
//class Date; // 类声明;已放入"datefwd.h"
Date today(); // 没问题,这里不需要Date的定义
void clearAppointments(Date d); // 同上
回到我们的Person类,下面是Person的两个成员函数的实现方式:
#include "Person.h" // 正在实现Person类,所以必须包含它的类定义
#include “PersonImpl.h” // 还必须包含PersonImpl的类定义
// 否则无法调用它的成员函数;
// 注意,PersonImpl具有与Person完全相同的接口
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();
}
Handle类方法的另一种选择是让Person成为一种特殊的抽象基类,称为接口类:
class Person {
public:
virtual ~Person();
virtual std::string name() const = 0;
virtual std::string birthDate() const = 0;
virtual std::string address() const = 0;
...
};
这个Person类作为基类提供接口接口,使用该类型的引用或指针,指向采用工厂设计模式创造的派生类对象。
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> // 返回类型为shared_ptr
create(const std::string& name, const Date& birthday, const Address& addr);
...
};
class RealPerson : public Person {
public:
RealPerson(const std::string& name, const Date& birthday, const Address& addr)
: theName(name), theBirthDate(birthday), theAddress(addr)
{}
virtual ~RealPerson() {}
std::string name() const; // 这里省略了实现细节
std::string birthDate() const;
std::string address() const;
private:
std::string theName;
Date theBirthDate;
Address theAddress;
};
std::tr1::shared_ptr<Person>
Person::create(const std::string& name,const Date& birthday,const Address& addr)
{
return std::shared_ptr<Person>(new RealPerson(name,birthday,addr));
}
std::string name;
Date dateOfBirth;
Address address;
...
// 创建一个支持Person接口的对象
std::shared_ptr<Person> pp(Person::create(name, dateOfBirth, address));
...
std::cout << pp->name() // 通过Person接口使用对象
<< " was born on " << pp->birthDate()
<< " and now lives at "<< pp->address();
...