Файл с объявлениями назван «datefwd.h» по аналогии с заголовочным файлом
Пример
В C++ есть также ключевое слово export, позволяющее отделить объявления шаблонов от их определений. К сожалению, поддержка компиляторами этой возможности ограничена, а практический опыт его применения совсем невелик. Сейчас еще слишком рано говорить, какую роль будет играть слово export в эффективном программировании на C++. Классы, подобные Person, в которых используется идиома pimpl, часто называют
#include “Person.h” // поскольку мы реализуем класс Person,
// то должны включить его определение
#include “PersonImpl.h” // мы должны также включить определение класса
// PersonImpl, иначе не сможем вызывать его
// функции-члены; отметим, что PersonImpl имеет
// в точности те же функции-члены, что и
// Person: их интерфейсы идентичны
Person::Person(const std::string& name, const Date& birthday,
const Address& addr)
: pImpl(new Person(name, birthday, addr))
{}
std::string Person::name() const
{
return pImpl->name();
}
Обратите внимание на то, как конструктор Person вызывает конструктор Personlmpl (используя new – см. правило 16), и как Person::name вызывает PersonImpl::name. Это важный момент. Превращение Person в класс-дескриптор не меняет его поведения – изменяется только место, в котором это поведение реализовано.
Альтернативой подходу с использованием класса-дескриптора – сделать Person абстрактным базовым классом специального вида, называемым
Интерфейсные классы сродни интерфейсам Java и. NET, но C++ не накладывают на интерфейсные классы тех ограничений, которые присущи этим языкам. Например, ни Java, ни. NET не допускают в интерфейсах наличия членов-данных и реализаций функций-членов. C++ этого не запрещает. Большая гибкость C++ в этом отношении может оказаться кстати. Как объясняется в правиле 36, реализация невиртуальных функций должна быть одинаковой для всех классов в иерархии, поэтому имеет смысл реализовать такие функции, как часть интерфейсного класса, в котором они объявлены.
Интерфейсный класс Person может выглядеть примерно так:
class Person {
public:
virtual ~Person();
virtual std::string name() const = 0;
virtual std::string birthDate() const = 0;
virtual std::string address() const = 0;
...
};