Pimpl: Короче говоря, шаблон pimpl действительно хорош для сокрытия частной реализации. Если вы хотели предоставить свои файлы заголовков для клиентов, которые должны были быть построены на основе вашего открытого интерфейса, но вы не хотели предоставлять свои подробности частной реализации, вы можете использовать шаблон pimpl, чтобы скрыть подробности. Вы сделали бы это по нескольким причинам, но в основном ваш заголовочный файл не должен был бы изменяться, когда вы изменяете частную реализацию изменений, что в противном случае заставило бы ваших клиентов перекомпилироваться. Таким образом, вы развязываете и скрываете свои личные детали реализации. Обычно вы должны держать указатель impl в контейнере RAII, как указатель unqiue, чтобы убедиться, что он освобождается при уничтожении.
Pimpl
// my_class.h
class my_class {
public:
// public here
private:
class impl; //forward declare impl
unique_ptr<impl> pimpl; // private implementation pointer
};
// my_class.cpp
class my_class::impl { // defined privately here
// ... all private data and functions: all of these
// can now change without recompiling callers ...
};
my_class::my_class(): pimpl( new impl )
{
// ... set impl values ...
my_class& operator=(my_class other);
friend void swap (my_class& lhs, myclass& rhs); // used for assignment
}
Swap , вероятно, возник, потому что когда вы выполняете оператор присваивания для этого класса и реализуете свою собственную процедуру подкачки для назначения членов, вам также необходимо знать о назначении этого указателя
my_class& my_class::operator=(my_class other)
{
swap(*this,other);
return *this;
}
void swap ( my_class& lhs, myclass& rhs )
{
using std::swap // now use default swap if override doesn't exist
// call swap for other members
// swap (lhs.data,rhs.data);
// call swap on unique_ptr
lhs.pimpl.swap(rhs.pimpl); // doesn't throw exceptions
}
Мост - это совершенно отдельный шаблон, который используется для объединения элементов вместе. Сходство между шаблонами состоит в том, что в вашем классе может быть метод процесса, который скрывает фактический вызов, поскольку он делегирует этот вызов содержащемуся в нем объекту, который будет обрабатывать фактический вызов метода. Другими словами, если у вас был базовый класс интерфейса запроса, который содержал указатель базового класса разработчика запроса. Следовательно, во время выполнения вы могли бы «соединить» системы, инициализируя мост определенным типом реализации запроса, но кто-то, вызывающий мост, просто вызовет метод запроса процесса, который делегирует вызов конкретному производному методу запроса разработчика во время выполнения. В Google есть несколько источников с хорошими диаграммами, которые также могут объяснить это более четко.