Re: Приведение типов в С/С++
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 05.03.02 09:14
Оценка: 9 (1)
Здравствуйте Libra, Вы писали:

L>Привет всем. Недавно для себя обнаружил некий оператор приведения типов

L>
L>
L>reinterpret_cast <BYTE*> ( variable );
L>

L>И сразу возник вопрос чем он отличается от обычного приведения типов?
L>например
L>
L>(unsigned char*)variable;
L>

L>Заранее благодарен.

Страуструп, 6.2.7
"... Оператор static_cast осуществляет преобразование родственных типов, ...
Оператор reinterpret_cast управляет преобразованиями между несвязанными типами, например целых в указатели ...
Такое различие позволяет компилятору осуществлять минимальную проверку типов при static_cast, а программисту — легче обнаружить опасные преобразования, представляемые reinterpret_cast. Некоторые преобазования static_cast являются переносимыми, но reinterpret_cast практически никогда не переносимо. Хотя никаких гарантий относительно reinterpret_cast дать нельзя, в результате обычно получается значение нового типа, состоящее из той же цепочки битов, что и аргумент преобразования. ...
Также имеется преобразование dynamic_cast, выполняемое и проверяемое на этапе выполнения, и const_cast, которое аннулирует действие модификатора const.
C++ унаследовал от С форму записи (T)e, означающую любое преобразование, ... для получения типа T из выражения e. Такой стиль намного опаснее, чем именованные операторы преобразования, потому что приведенную форму записи труднее отслеживать в большой программе и вид преобразования ... не очевиден. ... не зная конкретно типы T и e, невозможно сказать, что именно делает (T)e."

Вот так. То, что раньше делалось в С с помошью приведения типов T(e), в С++ стало гораздо сложнее по причине появления объектов, которых не было в С (например, указатели на функции-члены, множественное насдледование), и типы преобразований между голыми данными, принятые в С, были разделены на типы преобразований с разделением обязанностей. Теперь, используя один из перечисленных операторов, можно точно указать как компилятору, так и программисту, какой именно тип преобразования ожидается, и отслеживать возможные ошибки стало легче.

С уважением
Алексей Кирдин
Приведение типов в С/С++
От: Libra Россия  
Дата: 05.03.02 08:48
Оценка:
Привет всем. Недавно для себя обнаружил некий оператор приведения типов

reinterpret_cast <BYTE*> ( variable );

И сразу возник вопрос чем он отличается от обычного приведения типов?
например
(unsigned char*)variable;

Заранее благодарен.
Species come and go, but the earth stands forever fast...
Re: Приведение типов в С/С++
От: Willi  
Дата: 05.03.02 09:06
Оценка:
Здравствуйте Libra, Вы писали:

L>Привет всем. Недавно для себя обнаружил некий оператор приведения типов

L>
L>
L>reinterpret_cast <BYTE*> ( variable );
L>

L>И сразу возник вопрос чем он отличается от обычного приведения типов?
L>например
L>
L>(unsigned char*)variable;
L>

L>Заранее благодарен.

http://www.rsdn.ru/forum/message.asp?mid=634
Автор: IT
Дата: 27.04.01

http://www.rsdn.ru/forum/?gid=9&amp;mid=28970&amp;tid=28950
Автор: Алекс
Дата: 15.02.02

http://www.rsdn.ru/forum/message.asp?mid=27953
Автор: Vitaly Pigo
Дата: 11.02.02
\/\/i||i
Re: Приведение типов в С/С++
От: Brother Россия  
Дата: 05.03.02 09:14
Оценка:
Здравствуйте Libra, Вы писали:
L>Привет всем. Недавно для себя обнаружил некий оператор приведения типов
L>
L>
L>reinterpret_cast <BYTE*> ( variable );
L>

L>И сразу возник вопрос чем он отличается от обычного приведения типов?
L>например
L>
L>(unsigned char*)variable;
L>

L>Заранее благодарен.

В С++ введены следующие операторыприведения типов взамен приведения в стиле языка С.
Основная идея — сделать приведение типов более наглядным и понятным.
Дело в том, что при приведении типов в стиле С, т.е. например
(CClassA*) pObj;
не вполне понятно, что имеется ввиду. То ли происходит приведение указателя на потомок к указателю на базовый класс, то ли pObj — константный объект, и есть необходимость привести его к тому же классу, но не константному... То ли pObj указывает на массив байтов, которые нужно интерпретировать как объект класса CClassA... В каждом из случаев своя логика, свой смысл, свое назначение.
Для того, чтобы более четко выделить назначение и смысл приведения типов, в язык введены следующие операторы приведения типов
static_cast
const_cast
reintrepret_cast
dynamic_cast

Описание каждого из них несколько объемное, так что рекомендую посмотреть в книге, например, Страуструпа "Язык программирования С++", и задать вопросы (если возникнут).
С уважением,
Сергей
Re[2]: Приведение типов в С/С++
От: ynblpb  
Дата: 05.03.02 11:07
Оценка:
Если это кусочек из книги в электронном варианте.. подскажите где её можно достать... так сказать для просвящения... ЗЫ: заранее благодарен.
можть и я вам когда-нибудь помогу
Re[3]: Приведение типов в С/С++
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 05.03.02 12:12
Оценка:
Здравствуйте ynblpb, Вы писали:

Y>Если это кусочек из книги в электронном варианте.. подскажите где её можно достать... так сказать для просвящения... ЗЫ: заранее благодарен.


Есть на www.webdoc.ru, но только текст, без ссылок, без содержания одним куском (370К — жуть). Я брал из печатного варианта, а где есть нормальный электронный — не знаю.
Алексей Кирдин
Re: Приведение типов в С/С++
От: Pavel Ivlev www.vsi.ru/~pavel
Дата: 05.03.02 17:49
Оценка:
Ко всему сказанному хотел бы вот что добавить.
В отличие от static_cast, на результат работы reinterpret_cast нельзя полагаться ни в одном из случаев за исключением приведения к исходному типу. Все остальные применения в лучшем случае непереносимы. Вот почему преобразования между указателем на функцию и указателем на член относятся к reinterpret_cast, а не static_cast. Например:
void thump(char* p) { *p = 'x'; }

typedef void (*PF)(const char*);
PF pf;

void g(const char* pc)
{
   thump(pc); // ошибка: неправильный тип аргумента

   pf = &thump; // ошибка

   pf = static_cast<PF>(&thump); // ошибка!

   pf = reinterpret_cast<PF>(&thump); // допускается, но за последтсвия отвечаем только мы

   pf(pc); // правильная работа не гарантируется!
}


Присваивать pf указатель на thump опасно, т.к. это действие в обход системы типов. С помощью данной операции адрес константы может быть передан какой-то функции, которая сделает попытку ее модифицировать. Поэтому и нужно использовать приведение, причем именно оператор reinterpret_cast.

Оператор reinterpret_cast не осуществляет навигацию по иерархии классов. Например:
class A { /* ... */ };
class B { /* ... */ };
class D : public A, public И { /* ... */ };

void f(B* pb)
{
  D* pd1 = reinterpret_cast<D*>(pb);
  D* pd2 = static_cast<D*>(pb);
}


Здесь pd1 и pd2, как правило, получат различные значения.При вызове
f(new D);
pd2 будет указывать на начало переданного объекта D, а pd1 — на начало подобъекта B в объекте D.


Как говорит Страуструп: "Операция reinterpret_cast<T>(arg) почти так же неудачна, как и (T)arg."
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.