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.
2 ответа
Конструктор нуждается в доступе к удалителю точно так же, как и деструктор: исключительная безопасность требует, чтобы конструктор имел возможность откатить инициализацию всех членов в случае, если тело вашего конструктора выдает:
[C++14: 12.6.2/10]:
В не делегирующем конструкторе потенциально вызывается деструктор для каждого потенциально сконструированного подобъекта типа класса (12.4). [Примечание: это положение гарантирует, что деструкторы могут быть вызваны для полностью сконструированных подобъектов в случае возникновения исключения (15.2). —Конечная записка]
Связанные с:
"А" не может иметь конструктора.
Если вы прокомментируете созданный вами конструктор, компилятор сделает для вас конструктор по умолчанию, и он не обязательно будет в том же месте, где вы определили тот, который вы создали. Причинение указанной проблемы.