Я сомневаюсь, что этот конкретный случай UB. Во-первых, он просто приводит указатель от одного типа к другому. Поскольку здесь не задействовано виртуальное / множественное наследование, настройка указателя не выполняется, поэтому значение указателя остается неизменным. Конечно, это указывает на объект неправильного типа, но кого это волнует, если у нас нет доступа к членам B, даже если они есть? И даже если бы была задействована настройка указателя, все равно было бы хорошо, если бы мы не обращались к какой-либо памяти, указанной им, чего у нас нет.
Затем в примере вызывается метод B. Поскольку он не является виртуальным, это просто обычный вызов функции со скрытым аргументом this
(представьте себе B::B_Method(this)
). Теперь this
указывает на объект неправильного типа, но опять же, кого это волнует? Единственное, что он делает, - это печатает его, что всегда безопасно.
На самом деле, вы даже можете вызывать методы, используя нулевой указатель. Он работает до тех пор, пока метод не является виртуальным и не пытается получить доступ к чему-либо, указанному this
. Когда-то у меня была библиотека, используемая многими программами. Эта библиотека имела синглтоноподобный класс, который должен был быть создан явно, но на самом деле ни одна из программ не делала этого. Указатель экземпляра был инициализирован в NULL по умолчанию, поскольку он был глобальным. Это работало отлично, так как у класса не было членов данных вообще. Затем я добавил некоторые из них, и все программы неожиданно начали зависать. Когда я узнал причину, у меня был действительно хороший смех. Я использовал объект, который даже не существовал.