Операция static_cast используется для преобразования типа на этапе компиляции между:
□ целыми типами;
□ целыми и вещественными типами;
□ целыми и перечисляемыми типами;
□ указателями и ссылками на объекты одной иерархии, при условии, что оно однозначно и не связано с понижающим преобразованием виртуального базового класса.
Формат операции:
Static_cast <тип> (выражение)
Результат операции имеет указанный тип, который может быть ссылкой, указателем, арифметическим или перечисляемым типом,
При выполнении операции внутреннее представление данных может быть модифицировано, хотя численное значение остается неизменным. Например:
float f - 100:
int ,i = static_cast <int> (f);
// Целые и вещественные имеют различное внутреннее представление
Такого рода преобразования применяются обычно для подавления сообщений компилятора о возможной потере данных в том случае, когда есть уверенность, что требуется выполнить именно это действие. Результат преобразования остается на совести программиста.
Операция static_cast позволяет выполнять преобразования из производного класса в базовый и наоборот без ограничений:
class В{};
class С: public В{}: С с:
В *bp = static_cast<B*>(c): // Производный -> базовый В b:
С &ср = static_cast<C&>(b); // Базовый -> производный
Преобразование выполняется при компиляции, при этом объекты могут не быть полиморфными. Программист должен сам отслеживать допустимость дальнейших действий с преобразованными величинами.
В общем случае использование для преобразования указателей родственных классов иерархии предпочтительнее использовать операцию dynamic_cast. В этом случае если преобразование возможно на этапе компиляции, генерируется тот же код, что и для static_cast. Кроме того, dynamic_cast допускает перекрестное преобразование, нисходящее приведение виртуального базового класса и производит проверку допустимости приведения во время выполнения.
Операция dynamic_cast
Операция применяется для преобразования указателей родственных классов иерархии, в основном — указателя базового класса в указатель на производныйкласс, при этом во время выполнения программы производится проверка допустимости преобразования.
Формат операции:
dynamiccast <тип *> (выражение)
Выражение должно быть указателем или ссылкой на класс, тип — базовым или производным для этого класса. После проверки допустимости преобразования в случае успешного выполнения операция формирует результат заданного типа, в противном случае для указателя результат равен нулю, а для ссылки порождается исключение bad_cast. Если заданный тип и тип выражения не относятся к одной иерархии, преобразование не допускается.
Повышающее преобразование
Выполнение с помощью операции dynamic_cast повышающего преобразования равносильно простому присваиванию:
class В{ /* ... */ }:
class C: public В{ /* ... */ }:
C* с = new C:
В* b = dynamic_cast<B*>(c); // Эквивалентно В* b = с:
Понижающее преобразование
Чаще всего операция dynamic_cast применяется при понижающем преобразовании — когда компилятор не имеет возможности проверить правильность приведения.
Производные классы могут содержать функции, которых нет в базовых классах. Для их вызова через указатель базового класса нужно иметь уверенность, что этот указатель в действительности ссылается на объект производного класса. Такая проверка производится в момент выполнения приведения типа с использованием RTTI (run-time type information) — «информации о типе во время выполнения программы». Для того чтобы проверка допустимости могла быть выполнена, аргумент операции dynamic_cast должен быть полиморфного типа, то есть иметь хотя бы один виртуальный метод (см. с. 205).
Для использования RTTI необходимо подключить к программе заголовочный файл <typeinfo>. Кроме того, необходимо, чтобы был установлен соответствующий режим компилятора.
С помощью операции dynamic_cast такое преобразование возможно при условии, что класс является полиморфным и преобразование недвусмысленно. Рассмотрим пример, в котором выполняется понижающее преобразование виртуального базового класса:
#include <iostream.h>
#include <typeinfo.h>
class A{
public: virtual ~A(){};};
class B: public virtual A{}:
class С: public virtual A{};
class D: public B. public C{};
void demo(A *a){
D* d - dynamic_cast<D*>(a);
if (d) { ... }
}
int main(){
D *d - new D; demo(d); return 0:
}
Преобразование ссылок
Для аргумента-ссылки смысл операции преобразования несколько иной, чем для указателя. Поскольку ссылка всегда указывает на конкретный объект, операция dynaramic_cast должна выполнять преобразование именно к типу этого объекта. Корректность приведения проверяется автоматически, в случае несовпадения порождается исключение badcast:
Перекрестное преобразование
Операция dynamic_cast позволяет выполнять безопасное преобразование типа между производными классами одного базового класса.