Pimpl с std::unique_ptr в производном классе

Я не понимаю следующий сценарий. Речь идет об использовании идиомы pimpl на основе std::unique_ptr в производном классе. Дана простая иерархия классов, объявленная следующим образом:

class Foo
{
public:
  virtual ~Foo(); 
  //...
};

struct X;

class Bar : public Foo
{
public:
  ~Bar();
  //...

private:
  std::unique_ptr<X> _d;
};

Я показываю только код, соответствующий моему вопросу.

Представьте себе класс Foo будучи некоторым интерфейсом и классом 'Bar', который его реализует. Я хочу использовать идиому pimpl в Bar, Деструкторы являются виртуальными и определены в соответствующих файлах cpp. Также полное определение struct X, который только объявлен вперед, доступен в cpp, так что для деструктора Bar деструктор std::unique_ptr<X>::~unique_ptr() могут быть созданы Когда я пытаюсь создать экземпляр BarЯ бы ожидал, что это сработает

int main()
{
  Bar b;
}

Вместо этого я получаю сообщение об ошибке компиляции с неопределенным типом 'X', за которым следует сообщение, что невозможно удалить неполный тип (в Visual Studio 2013 Update 2). Однако, если я явно добавлю конструктор по умолчанию в Bar, main() компилирует / строит правильно.

class Foo
{
public:
  virtual ~Foo(); 
};

struct X;

class Bar : public Foo
{
public:
  Bar();
  ~Bar();

private:
  std::unique_ptr<X> _d;
};

Я не вижу соответствия между наличием конструкторов по умолчанию в этой иерархии классов и полнотой struct X в контексте std::unique_ptr<X> в Bar, Может ли кто-нибудь объяснить или указать на возможно уже существующее объяснение?

1 ответ

Проблема в том, что конструктор по умолчанию добавлен в Bar должен позвонить std::unique_ptr<X>деструктор на всякий случай Barконструктор выдает исключение.

Но std::unique_ptr<X>::~unique_ptr() вызывает Deleter unique_ptr: std::default_delete<X> - что требует X быть полным типом. [Unique.ptr.single.dtor]

Когда вы сами объявляете конструктор, его создание не происходит, потому что конструктор только объявляется и, таким образом, связывается в более поздний момент времени, и компилятор с удовольствием ест ваш код.

Другие вопросы по тегам