Обычно стандарт говорит, что он не будет работать (dynamic_cast) во время создания объекта.
Редактировать: Добавлено на основе комментария VJo ниже.
Примечание: приведение от 'B' к 'A' с использованием динамического приведения должно работать, потому что мы приводим объект извведите «C».Если мы добавим следующий код в main:
B bObj;
B& bRef = c;
B* bPtr = &c;
std::cout << !!dynamic_cast<A*>(&bObj) << std::endl;
std::cout << !!dynamic_cast<A*>(&bRef) << std::endl;
std::cout << !!dynamic_cast<A*>( bPtr) << std::endl;
Дополнительный вывод будет:
0 // Can not convert a B to an A
1 // Can convert this B to an A because it is really a C.
1 // This is what we are reeling doing in B::B() that fails
// It is not the dynamic_cast<> that fails but the conversion of this from C* to B*
// That is causing UB
В конструкторе произойдет сбой, поскольку объект сформирован не полностью.Используя это, мы пытаемся преобразовать указатель C в указатель B до запуска конструктора C (код, определенный пользователем).Таким образом, использование this
в B :: B () в качестве указателя на объект C завершается неудачно, поэтому при вызове dynamic_cast <> он не может выполнить то, что вам нужно, из-за UB.
12.7 Построение и уничтожение [class.cdtor]
Пункт 3
Для явного или неявного преобразования указателя (glvalue), ссылающегося на объект класса X, в указатель (ссылка) к прямому или косвенному базовому классу B X, должно начаться строительство X и построение всех его прямых или косвенных оснований, которые прямо или косвенно являются производными от B, и уничтожение этих классов не должно быть завершено, в противном случаеконверсия приводит к неопределенному поведению.Чтобы сформировать указатель на (или получить доступ к значению) прямого нестатического члена объекта obj, должно начаться построение obj, а его уничтожение не должно быть завершено, в противном случае вычисление значения указателя (или доступ к члену)значение) приводит к неопределенному поведению.
[Пример:
struct A { };
struct B : virtual A { };
struct C : B { };
struct D : virtual A { D(A*); };
struct X { X(A*); };
struct E : C, D, X
{
E() : D(this), // undefined: upcast from E* to A*
// might use path E* → D* → A*
// but D is not constructed
// D((C*)this),
// defined:
// E* → C* defined because E() has started
// and C* → A* defined because
// C fully constructed
X(this) { // defined: upon construction of X,
// C/B/D/A sublattice is fully constructed
}
};
- конец примера]