Unique_ptr и предварительное объявление

Скажем, у меня есть два класса:

"Foo.h"

#pragma once    
class Foo
{
public:
    Foo()
    {

    };

    ~Foo()
    {

    };
};

"Ах"

#pragma once
#include <memory>

class Foo;

class A
{
public:
    A(){};
    ~A(){};

    std::unique_ptr<Foo> foo;
};

А держит unique_ptr из Foo, Я не хотел включать Foo в "Ах", так что я вперед объявил об этом. Просто вперед объявив класс Foo в "А" я получаю ошибку времени компиляции:

error C2027: use of undefined type 'Foo'
error C2338: can't delete an incomplete type  

Поэтому я следил за этой статьей о том, как избежать этой ошибки, и переместил деструктор А в его собственный файл.cpp, где я также включил Foo:

"A.cpp"

#include "A.h"

#include "Foo.h"

A::A()
{

}

A::~A()
{

}

После реализации деструктора A в "A.cpp" я могу скомпилировать программу, потому что класс Foo известен в "A.cpp". Это кажется логичным, потому что unique_ptr нужен полный тип, чтобы вызвать его деструктор. Но, к моему удивлению, после комментирования конструктора A (в "Ah" и "A.cpp") я получаю ту же ошибку. Как это возможно? Почему компилятор жалуется, что не может вызвать деструктор Foo, когда A не имеет конструктора?

РЕДАКТИРОВАТЬ: я загрузил 4 файла, чтобы вы могли проверить программу. Я использую MSVC++ Visual Studio 2013.

http://www.filedropper.com/test_61

2 ответа

Конструктор нуждается в доступе к удалителю точно так же, как и деструктор: исключительная безопасность требует, чтобы конструктор имел возможность откатить инициализацию всех членов в случае, если тело вашего конструктора выдает:

[C++14: 12.6.2/10]: В не делегирующем конструкторе потенциально вызывается деструктор для каждого потенциально сконструированного подобъекта типа класса (12.4). [Примечание: это положение гарантирует, что деструкторы могут быть вызваны для полностью сконструированных подобъектов в случае возникновения исключения (15.2). —Конечная записка]

Связанные с:

"А" не может иметь конструктора.

Если вы прокомментируете созданный вами конструктор, компилятор сделает для вас конструктор по умолчанию, и он не обязательно будет в том же месте, где вы определили тот, который вы создали. Причинение указанной проблемы.

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