Воскресенье, 19.05.2024, 04:35Приветствую Вас Гость | RSS
IT Solutions
Меню сайта
Наш опрос
Оцените мой сайт
Всего ответов: 407
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Блог


Главная » 2013 » Ноябрь » 18 » Преобразования типа в C++:
06:14
Преобразования типа в C++:

Неявные преобразования типов часто приводят к ошибкам, которые не всегда легко заметить  и быстро обнаружить.

 

Поэтому сегодня я расскажу о новых операторах приведения, которые позволяют более строго оформлять свои мысли и чётче их формулировать.

 

/*********************************************************************************************

**********************************************************************************************

*********************************************************************************************/

Первый:  const_cast < type > ( return_value )

/* Позволяет добавлять или удалять квалификаторы типов "const" и "volatile" из типов выражения.

      const Person*  getName()   {  /* тело функции */ }  

      Person*  anName = const_cast < Person* > (   getName()   );

/* "const_cast" аннулировал "const" в типе значения, возвращаемого функцией getName() */

 

Эквивалентно худшему варианту: 

      anName = ( Person* ) getName();

 

Плюсы "const_cast":

   1) Он бросается в глаза, поэтому видно, что было преобразование типа.

   2) Если будет изменение функции getName из const Person* getName() в const Name* getName(), то     компилятор сообщит об этом, так как возможности "const_cast" ограничены.

 

/*********************************************************************************************

**********************************************************************************************

*********************************************************************************************/

Второй: static_cast < type > ( return_value )

/* Применяется для переносимых на разные платформы приведений. Чаще всего служит для приведения "вниз" по иерархии наследования от указателя (или ссылки) на базовый класс к указателю (или ссылке) на производный класс. */

     Shape* sp = new Circle;

     Circle*  cp = static_cast < Circle* > ( sp ); 

/* Компилируется, потому что "sp" действительно ссылается на объект "Circle".

Но если бы "sp" указывал на какой-нибудь другой тип "Rectangle", то при использовании "cp" получил бы, скорее всего, ошибку. */

 

Вывод: static_cast не меняет квалификаторы типа так, как это может const_cast

      const Shape*  getShape()   { /* тело функции */ }

      Circle*  cp = static_cast < Circle* > (      const_cast <Shape* > (  getShape()  )      );  

 

/*********************************************************************************************

**********************************************************************************************

*********************************************************************************************/

Третий: reintepret_cast < type > ( type2 );

/* Обычно работает с битами объекта и позволяет осуществлять преобразования между совершенно несвязными типами.  */

    HP = reinterpret_cast < char* > ( 0x0f0... ) /* преобразует целое в указатель */

    /* теперь будем преобразовывать char* в int* */

    int* PW = reinterpret_cast < int* > ( HP );

 

Выводы: 

  1) Такие преобразования в коде низкого уровня не являются непереносимыми.

  2) reinterpret_cast обычно считает, что указатель на базовый класс является указателем на производный класс и не меняет его значение. А static_cast осуществляет правильную работу с адресами.

 

/*********************************************************************************************

**********************************************************************************************

*********************************************************************************************/

Четвёртый: dynamic_cast  

/* Обычно применяется для безопасного нисходящего приведения от указателя на базовый класс к указателю на производный класс.

    От static_cast отличается тем, что нисходящее преобразование может осуществляться только для полиморфного типа ( то есть тип приводимого выражения должен быть указателем на тип класса с виртуальной функцией ).

   Правильность приведения проверяется во время выполнения. И если у statc_cast издержки времени минимальны, то dynamic_cast предполагает более существенные издержки времени выполнения.

     const Circle* cp = dynamic_cast < const Circle* > (  getShape()  );

/* Если getShape возвращает указатель на Circle (или какой-то наследуемый от Circle класс), то приведение будет успешным и cp будет указывать на Circle. Иначе cp будет нулевым.

    Удобно в if (  )   { /*   */} поместить объявление "const Circle* ... ". Тогда cp, когда в нём исчезнет необходимость, сам уйдёт из области видимости.

 

    const Circle& rc = dynamic_cast < const Circle& > (  *getShape( )  );

/*Приведение аналогично,но вместо возврата нулевого указателя формирует исключение std::bad_cast */

 

   Применение dynamic_cast к указателю это вопрос:

"Этот указатель на Shape фактически указывает на Circle? Если нет, я могу заняться этим!"

 

   Применение dynamic_cast к ссылке это утверждение:

"Предполагается, что этот Shape есть не что иное, как Circle. Если это не так, значит что-то не в порядке!"

Категория: С/C++ | Просмотров: 1362 | Добавил: B@R_LOG | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа
Категории раздела
Полезное [0]
Windows [0]
С/C++ [6]
SEO [0]
WEB [0]
Поиск
Друзья сайта
  • МЫ в "ВКонтакте"
  • Архив записей
    Календарь
    «  Ноябрь 2013  »
    ПнВтСрЧтПтСбВс
        123
    45678910
    11121314151617
    18192021222324
    252627282930
    Система Orphus