У меня есть особая иерархия классов, которая дает сбой во время выполнения (Visual Studio 2017).
struct A{};
struct B
{
auto f()
{
dynamic_cast<A *>(this);//triggers: Access violation
}
virtual ~B() = default;
};
struct C :virtual B, A//remove "virtual" to fix
{
C()
{
f();
}
int a;//remove to fix
};
struct D :virtual C{};//remove "virtual" to fix
int main()
{
D d;
}
Вопрос такой: Это проблема кода или, скорее, ошибка компилятора?
Я пробовал множество вариантов, но ни один из них не удовлетворил меня, так как этот код мне кажется правильным.
@ FrançoisAndrieux Это зависит от того, чего ожидает ты! В конструкторе подобъекта невиртуальной базы без виртуальной базы виртуальные функции, dynamic_cast и все остальное ведут себя точно так же, как в конструируемом полном классе этого типа, даже с абстрактным классом, который только что завершился с недопустимым определением чистой виртуальной функции. На практике во всех реализациях все соответствует поведению всего класса: макет, значение всех vptr, поэтому формализация ожиданий проста. Это неверно, если у вас есть виртуальные базы, поскольку базовый объект не похож на законченный объект.
@ FrançoisAndrieux В каких конкретных случаях dynamic_cast будет плохо себя вести при использовании на строящемся субъекте базового класса, где задействовано виртуальное наследование? (Конечно, dynamic_cast<T>(this) не будет использоваться с преждевременным this.)
Выложите пожалуйста смещения подобъектов в C vs D
"int a;//remove to fix" Я полагаю, что C::a заставляет D расти, поскольку не позволяет C быть первичным в полном D, что меняет ... что-то. Выложите пожалуйста оверхед D с C::a и без него.
@ FrançoisAndrieux Единственные виртуальные функции, которые вы никогда не можете вызывать из конструктора, - это прямой вызов деструктора (this->~T();) и удаление деструктора (delete this;)
@Acorn "На этот вопрос уже есть ответ здесь" Правда? Где?
Похоже, я должен признать полиморфизм недоступным в конструкторах. Жалко, что предупреждений нет, и это легко игнорировать.
@Pjoter Полиморфизм отлично работает в конструкторах!





dynamic_castне всегда работает должным образом при вызове из конструктора, подобно тому как функцииvirtualне всегда делают то, что вы ожидаете.