Рассмотрим этот классический пример, используемый для объяснения того, что не делать с предварительными декларациями:
//in Handle.h file
class Body;
class Handle
{
public:
Handle();
~Handle() {delete impl_;}
//....
private:
Body *impl_;
};
//---------------------------------------
//in Handle.cpp file
#include "Handle.h"
class Body
{
//Non-trivial destructor here
public:
~Body () {//Do a lot of things...}
};
Handle::Handle () : impl_(new Body) {}
//---------------------------------------
//in Handle_user.cpp client code:
#include "Handle.h"
//... in some function...
{
Handle handleObj;
//Do smtg with handleObj...
//handleObj now reaches end-of-life, and BUM: Undefined behaviour
}
Из стандарта я понимаю, что этот случай направлен в сторону UB, поскольку деструктор Body не тривиален.
То, что я пытаюсь понять, действительно является коренной причиной этого.
Я имею в виду, что проблема, кажется, "вызвана" тем фактом, что dtor в Handle является встроенным, и поэтому компилятор делает что-то вроде следующего "встроенного расширения" (здесь почти псевдокод).
inline Handle::~Handle()
{
impl_->~Body();
operator delete (impl_);
}
Во всех единицах перевода (в данном случае только Handle_user.cpp
), где экземпляр Handle будет уничтожен, верно?
Я просто не могу этого понять: хорошо, когда генерируется вышеупомянутое встроенное расширение, компилятор не имеет полного определения класса Body, но почему он не может просто разрешить компоновщик для вещи impl_->~Body()
и поэтому должен вызвать его функция деструктора Body, которая фактически определена в его файле реализации?
Другими словами: я понимаю, что в момент уничтожения дескриптора компилятор даже не знает, существует (нетривиальный) деструктор для Body или нет, но почему он не может делать так, как всегда, что ли оставить заполнитель для заполнителя компоновщика и, в конечном итоге, получить компоновщик "неразрешенный внешний", если эта функция действительно недоступна?
Я что-то упускаю здесь (и в таком случае извините за глупый вопрос)?
Если это не так, мне просто любопытно понять причину этого.