Реализация dynamic_cast

#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 классов!