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;
};
A содержит a unique_ptr
of Foo
. Я не хотел включать Foo
в "A.h" , поэтому я просил объявить его. Просто объявив класс Foo
в "A.h" , я получаю ошибку времени компиляции:
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 (в "A.h" , а также "A.cpp" ), я получаю ту же ошибку. Как это возможно? Почему компилятор жалуется на невозможность вызвать Foo destructor, когда A не имеет конструктора?
EDIT:
Я загрузил 4 файла, чтобы вы могли протестировать программу.
Я использую MSVС++ Visual Studio 2013.
http://www.filedropper.com/test_61
Ответы
Ответ 1
Конструктор нуждается в доступе к делетеру точно так же, как это делает деструктор: безопасность исключений требует, чтобы конструктор смог откатить инициализацию всех членов в случае, когда тело вашего конструктора выбрасывает:
[C++14: 12.6.2/10]:
В конструкторе без делегирования потенциально вызывается деструктор для каждого потенциально сконструированного подобъекта типа класса (12.4). [Примечание. Это условие гарантирует, что деструкторы могут быть вызваны для полностью построенных под-объектов в случае возникновения исключения (15.2). -end note]
по теме:
Ответ 2
Невозможно, чтобы "A" не имел конструктора.
Если вы прокомментируете созданный вами конструктор, компилятор сделает для вас конструктор по умолчанию, и он не обязательно будет в том же месте, в котором вы определили тот, который вы создали. Вызвать указанную проблему.