Разные способы приведения типов
От: Vamp Россия  
Дата: 28.01.04 08:57
Оценка: 123 (16) +1
#Имя: FAQ.cpp.casts
К>... Подкиньте плиз линки, где хорошо написано про:
Три источника и три составные части: Мейерс, Саттер, Страуструп.

К>1. Все типы *_cast'ов, сравнение их между собой и с С-шным стилем, описаны различия.

Существует четыре точка 1 (по аналогии с DD 5.1) типа кастов — static_cast, dynamic_cast, const_cast и reinterpret_cast. .1 — это С-каст. Новые касты были введены вместо С-кастов в основном по двум причинам — для облегчения поиска преобразований в теле программы (для этого достаточно простого текстового поиска по "_cast") и уточнения намерений программиста. Кроме того, С-касты не в состоянии обеспечить функциональность dynamic_cast. Соответственно, они предлагают значительные преимущества по сравнению с традиционными С-кастами.
К>2. Что конкретно происходит при вызове каждого из cast'ов, как обстоят дела, если например переопределён оператор приведения типа.
1. static_cast.
Используется для преобразований, основанных на статической проверке типов. Может применяться для преобразования перечислений в целые, целых во флоаты, казателя на базовый класс в указатель на производный класс. "Дешевый" оператор, не налагающий никаких накалдных расходов во время исполнения. Зачастую может вызываться неявно. Не способен выполнять "неродственные" преобразования, например из void* в int* или из А в несвязанный с ним родственными отношениями В, если не определены собственные операторы преобразования типов. В случае приведения указателя на базовый класс к указателю на потомка может оказаться небезопасным — гарантий того, указатель в момент выполнения будет указывать на экземпляр класса потомка, нет.
При необходимости статик-каст может вызывать пользовательские операторы преобразования типов.
2. dynamic_cast.
С-каст не способен реализовать его функциональность. Отличается от статик каста проверкой типов во время выполнения, следовательно, его использование сопряжено с накладными расходами и требует включения RTTI (Run-time type information), однако безопасно. Существует в двух формах — указательной и ссылочной. Пример:

class A {};
class B : public A {};
...
A a;
B b;

A* pa=&b;
A& ra=b;

B* pb=dynamic_cast<B*>(pa); //указательная форма
B& rb=dynamic_cast<B&>(ra); //ссылочная форма


Формы различаются поведением. в случае если во время выполнения программы проверка типов показала, что преобразование некорректно (например, указателя не указывает на объект запрашиваемого типа). Указательная форма возвращает нулевой указатель, а ссылочная генерирует исключени bad_cast.

3. const_cast.
Используется для снятия атрибутов const и volatile, что не способны сделать другие касты. Его нельзя использовать для преобразования типов по аналогии с предыдущими кастами. Применение этого оператора "успокаивает" компилятор на предмет изменения константного объекта, однако способно привести к неопределенному поведению, в случае, если память по данному адресу окажется непредназначенной для чтения на более низком уровне (например, заблокирована ОС). Может снять атрибут константности с this и вызывать неконстные методы внутри класса. Например:


struct A {
   void f() {};
   void cf() const;
};

void A::cf() {
   f(); //compilation error
   const_cast<A*>(this)->f(); //ok, but probably unsafe
}

...
const A a;
a.cf();


4. reinterpret_cast.
Компилятор умывает руки. Используется для преобразований указателей на что угодно в указатели на что угодно другое. Единственное безопасное использование — преборазование туда и затем обратно. Все прочее — на совести программиста. Использование его в современной программе — повод всерьез задуматься о дизайне, современный С++ позволяет практически полностью от него отказаться. Однако, необходимо при использовании унаследованных библиотек.

struct A{
   void f() {}
};
...
int i;
int *pi=&i;
A* pa=reintrepret_cast<A*>(pi);
pa->f(); //WHAT A MESS!! But compiles OK.


4.1 С-каст
Когда компилятор С++ видит С-каст, он по собственному разумению вызывает один из трех _кастов. Рекомендуется заменять на явное использование _каста для демонстрации намерений программиста.

К>3. Плюсы и минусы использования cast'ов.

Касты (особенно reinterpret) зачастую свидетельсвтуют о плохом дизайне программы. Их использование следует минимизировать, каждое появление в коде документировать, обосновывая их появление.
Да здравствует мыло душистое и веревка пушистая.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.