Вызывает ли тернарный оператор в сочетании с преобразованием указателей вверх в стиле C неопределенное поведение в этом случае?

Мотивирующая предыстория: Пытаясь отладить трудновоспроизводимую неисправность в своем программном обеспечении, я наткнулся на сомнительный код приведения указателей, написанный наивным младшим разработчиком (ладно, признаю, это был я, 10 лет назад), что, как я подозреваю, может быть основной причиной неисправности.

Я переписал код, чтобы вместо этого использовать правильные вызовы static_cast<>, и я не видел, чтобы возникало состояние ошибки после перезаписи, но это не обязательно означает что-либо, учитывая, что ошибка все равно возникает редко; Мне пока может просто везти.

Мой вопрос: вызывает ли преобразование указателей в стиле C, выполненное внутри main() в приведенном ниже коде, неопределенное поведение? Или это просто некрасиво, но тем не менее хорошо сформировано с точки зрения юриста по языку?

#include <stdio.h>
#include <stdlib.h>

class BaseClass
{
public:
   BaseClass() {}
   virtual ~BaseClass() {}

   virtual void Foo() {printf("BaseClass::Foo() called\n");}
};

class SubClassA : public BaseClass
{
public:
   SubClassA() {}

   virtual void Foo() {printf("SubClassA::Foo() called\n");}
};

class SubClassB : public BaseClass
{
public:
   SubClassB() {}

   virtual void Foo() {printf("SubClassB::Foo() called\n");}
};

int main(int, char **)
{
   SubClassA a;
   SubClassB b;

   // Warning:  questionable C-style casting follows...
   BaseClass * p = (rand()%2) ? ((BaseClass*)(&a)) : ((BaseClass*)(&b));
   p->Foo();

   return 0;
}

person Jeremy Friesner    schedule 31.07.2020    source источник
comment
Если тернарный оператор в сочетании с любым приведением дает какой-либо нежелательный результат, я готов поспорить на хороший ужин (ресторан - мой выбор), что в основе проблемы НЕ тернарный оператор. Это всегда кастинг (или что-то, что вы вообще пропустили).   -  person Yunnosch    schedule 31.07.2020
comment
Если преобразование в стиле C допустимо с самого начала, я не вижу причин, по которым оно могло бы стать неопределенным при включении в условный оператор.   -  person Barmar    schedule 31.07.2020
comment
Тип условного оператора становится запутанным только тогда, когда истинное и ложное подвыражения относятся к разным типам — общий тип должен быть определен для всего выражения. Но это не проблема здесь.   -  person Barmar    schedule 31.07.2020


Ответы (1)


Состав полностью легальный. Из [expr.cast]/4.6

указатель на объект типа производного класса или lvalue или rvalue типа производного класса может быть явно преобразован в указатель или ссылку на однозначный тип базового класса, соответственно;

person NathanOliver    schedule 31.07.2020