#c
#c
Вопрос:
Следующий код создает этот вывод:
1 is a null pointer
2 is not a null pointer
Код
class base {};
class derived1: public base {};
class derived2: public base {};
int main() {
base *baseptr[1];
baseptr[0] = new derived2;
derived1 *derptr = new derived1;
derived1 *derivedptr1 = dynamic_cast<derived1*>(baseptr[0]);
derived1 *derivedptr2 = dynamic_cast<derived1*>(derptr);
cout<<((derivedptr1==0)?"1 is null pointer":"1 is not a null pointer") << endl;
cout<<((derivedptr2==0)?"2 is null pointer":"2 is not a null pointer") << endl;
}
Почему derivedptr2 только инициализирован, а derivedptr1 — нет? Поскольку оба имеют допустимое значение в правой части. Имеет ли это какое-то отношение к динамическому приведению и тому факту, что во втором случае я преобразую derived1* в derived1 *?
Комментарии:
1. Пожалуйста, сначала объясните, что вас смущает или странно в выходных данных.
2. Почему вы включили
static_cast
в заголовок, когда в самом вопросе даже не упоминаетсяstatic_cast
?
Ответ №1:
Во-первых, ваш код не поддается компиляции. Для того, чтобы использовать dynamic_cast
для чего-либо еще, кроме upcasts, вам нужен полиморфный тип в качестве операнда указателя. Вы используете его для [попытки] перекрестного приведения, и ваши типы не являются полиморфными.
Во-вторых, если вы делаете свои классы полиморфными (чтобы код компилировался), то поведение, о котором вы сообщаете, действительно является ожидаемым поведением. derivedptr1
Указатель действительно должен быть нулевым, поскольку derived2
object не является derived1
объектом (и рассматриваемые объекты не являются частями какого-либо общего суперобъекта). Перекрестное приведение завершается ошибкой, и dynamic_cast
поэтому вычисляется нулевой указатель. Вы ожидали чего-то другого?
Во втором случае (для derivedptr2
) у вас есть приведение «идентификатора» из derived1 *
в derived1 *
. Тип тот же, поэтому это приведение, по сути, не выполняется. Он просто принимает исходное значение.
Ответ №2:
*dynamic_cast* используется для проверки достоверности пониженной рассылки.
Он возвращает действительный указатель, если указатель действительно указывает на приводимый тип или класс, производный от класса, на который указывается.
baseptr[0]
указывает на тип derived2
.
С помощью
dynamic_cast<derived1*>(baseptr[0]);
Вы пытаетесь проверить, basepte[0]
действительно ли указывает на derived1
или производный от него класс. Очевидно, что это ни то, ни другое, поэтому он возвращает 0
.
Аналогично, derptr
указывает на тип derived1
.
С помощью
dynamic_cast<derived1*>(derptr);
Вы пытаетесь проверить, derptr
указывает на derived1
, что правильно, следовательно, он возвращает допустимый тип указателя, в результате чего выводится значение Not null.
Предостережение: как справедливо отметил @AndreyT, dynamic_cast
работает только для Polymorphic
классов!