Как уже упоминалось в двух других ответах, тип объекта изменяется по мере выполнения деструкторов.Как только деструктор завершает работу, объект этого типа больше не существует, и существуют только его базовые подобъекты (пока не завершены их деструкторы).
Причиной этого ответа является предложение интересного эксперимента.этот код будет?(О, хорошо, все три ответа уже сказали вам, но эксперимент интересен сам по себе):
#include <iostream>
struct base {
static void print_type( base const & b ) { // [1]
std::cout << b.type() << std::endl;
}
virtual std::string type() const { // [2]
return "base";
}
virtual ~base() { print_type( *this ); }
base() { print_type( *this ); }
};
struct derived : base {
std::string type() const {
return "derived";
}
~derived() { print_type( *this ); }
derived() { print_type( *this ); }
};
struct most_derived : derived {
std::string type() const {
return "most_derived";
}
~most_derived() { print_type( *this ); }
most_derived() { print_type( *this ); }
};
int main() {
most_derived md;
base::print_type( md );
}
Примечания:
Для дополнительного удовольствия добавлены также звонки на print_type
в конструкторе.Функция служит для проверки динамического типа объекта в данный конкретный момент времени.Функция print_type
(это может быть автономная функция, реализованная в другом модуле перевода - чтобы избежать того, что компилятор увидит внутри нее).При компиляции функции компилятор не может знать, вызывается ли она из конструктора, деструктора или вне их, поэтому сгенерированный код должен использовать механизм динамической диспетчеризации и будет отправлен в окончательное переопределение в каждый момент времени.
В отношении действительности кода гарантируется §12.7 / 2:
Для явного или неявного преобразованияуказатель (значение l), ссылающийся на объект класса X на указатель (ссылку) на прямой или косвенный базовый класс B из X, конструкцию X и построение всех его прямых или косвенных баз, которые прямо или косвенно происходят изB должен начаться, и уничтожение этих классов не должно быть завершено, в противном случае преобразование приводит к неопределенному поведению.Чтобы сформировать указатель на (или получить доступ к значению) прямого нестатического члена объекта obj, должно начаться построение obj, а его уничтожение не должно быть завершено, в противном случае вычисление значения указателя (или получение доступа к значению элемента)приводит к неопределенному поведению.
Преобразования в base&
при вызове print_type
действительны, так как они выполняются после построения каждого объекта и доуничтожение каждого объекта завершено ( каждый относится к каждому из подобъектов most_derived
в программе).