В настоящее время я изучаю идиому pimpl, и есть очень хорошие руководства по ее реализации (например, здесь). Но я никогда не видел, чтобы он был реализован как базовый класс шаблона, например:
#ifndef PIMPL_H
#define PIMPL_H
template <class T>
class Pimpl
{
public:
explicit Pimpl();
explicit Pimpl(T *ptr);
virtual ~Pimpl() = 0;
Pimpl(const Pimpl<T> &other);
Pimpl &operator=(const Pimpl<T> &other);
protected:
T *d_ptr;
};
template<class T>
Pimpl<T>::Pimpl() : d_ptr(new T)
{
}
template<class T>
Pimpl<T>::Pimpl(T *ptr) : d_ptr(ptr)
{
}
template<class T>
Pimpl<T>::~Pimpl()
{
delete d_ptr;
d_ptr = 0;
}
template<class T>
Pimpl<T>::Pimpl(const Pimpl<T> &other) : d_ptr(new T(*other.d_ptr))
{
}
template<class T>
Pimpl<T> &Pimpl<T>::operator=(const Pimpl<T> &other)
{
if (this != &other) {
delete d_ptr;
d_ptr = new T(*other.d_ptr);
}
return *this;
}
#endif // PIMPL_H
Который затем можно было бы использовать в любом классе, который вам нравится pimpl:
#ifndef OBJECT_H
#define OBJECT_H
#include "pimpl.h"
class ObjectPrivate;
class Object : public Pimpl<ObjectPrivate>
{
public:
Object();
virtual ~Object();
/* ... */
};
#endif // OBJECT_H
В настоящее время я использую его в небольшом примерном проекте (сборке в качестве разделяемой библиотеки), и единственная проблема, с которой я столкнулся, заключалась в том, что MSVC предупреждает об отсутствии деструктора для ObjectPrivate (см. C4150). Это предупреждение возникает только потому, что ObjectPrivate объявлен заранее и поэтому не виден оператору удаления в Pimpl::~Pimpl() во время компиляции.
Кто-нибудь видит какие-либо проблемы с этим подходом? :-)
Итак, теперь есть окончательная версия на основе приведенного ниже обсуждения на GitHub (большое спасибо StoryTeller). репозиторий также содержит простой пример использования.
Pimplдругом. - person StoryTeller - Unslander Monica   schedule 22.05.2017unmakeиcloneнедоступны в пределах_unmakeи_clone. Если я компилирую с открытым наследованием, компилятор жалуется на недопустимое использование класса неполного типа ObjectPrivate в пределахclone. Он также предупреждает о том, чтоpвunmakeимеет неполный тип. - person 0x2648   schedule 22.05.2017object.cpp. Они не могут быть встроенными - person StoryTeller - Unslander Monica   schedule 22.05.2017std::unique_ptr<ObjectPrivate>? Или протестировать свой проект с помощью GCC и/или clang? Я сильно подозреваю, что это проблема с MinGW. Элементы шаблонов не создаются до тех пор, пока они не будут использованы (согласно стандарту C++). Вот почему рекомендации по реализации. Ваш проект в порядке с первого взгляда. - person StoryTeller - Unslander Monica   schedule 22.05.2017std::unique_ptr<ObjectPrivate> d_ptrвместо наследованияPimplпрекрасно работает (если вы не возражаете, что объект больше нельзя копировать). Я смог протестировать реализацию по умолчанию только с MSVC 2015, которая ведет себя точно так же, как MinGW. - person 0x2648   schedule 22.05.2017Objectне объявляетoperator=, поэтому компилятор генерирует один встроенный. Поэтому создается и вызывается определениеPimpl::operator=, в результате чего клон пытается скопировать неполный тип. Так что этот проект не учел мой исходный комментарий - person StoryTeller - Unslander Monica   schedule 22.05.2017