между:
• целыми типами;
• целыми и вещественными типами;
• целыми и перечисляемыми типами;
• указателями и ссылками на объекты одной иерархии, при условии, что оно однозначно и не связано с понижающим преобразованием виртуального базового класса.
static_cast <тип> (выражение)
Результат операции имеет указанный тип, который может быть ссылкой, указателем, арифметическим или перечисляемым типом. При выполнении операции внутреннее представление данных может быть модифицировано, хотя численное значение остается неизменным. Операция static_cast позволяет выполнять преобразования из производного класса в базовый и наоборот без ограничений.
Преобразование выполняется при компиляции, при этом объекты могут не быть полиморфными. Программист должен сам отслеживать допустимость дальнейших действий с преобразованными величинами.
В общем случае использование для преобразования указателей родственных
классов иерархии предпочтительнее использовать операцию dynamic_cast. В этом случае если преобразование возможно на этапе компиляции, генерируется тот же код, что и для static_cast. Кроме того, dynamic_cast допускает перекрестное преобразование, нисходящее приведение виртуального базового класса и производит
проверку допустимости приведения во время выполнения.
ТИПЫ ПРЕОБРАЗОВАНИЙ
Понижающее преобразование
Чаще всего операция dynamic_cast применяется при понижающем преобразовании
— когда компилятор не имеет возможности проверить правильность приведения.
Производные классы могут содержать функции, которых нет в базовых классах. Для их вызова через указатель базового класса нужно иметь уверенность, что этот указатель в действительности ссылается на объект производного класса. Такая проверка производится в момент выполнения приведения типа с использованием RTTI (run-time type information) — «информации о типе во время выполнения программы». Для того чтобы проверка допустимости могла быть выполнена, аргумент операции dynamic_cast должен быть полиморфного типа, то есть иметь хотя бы один виртуальный метод. Для полиморфного объекта реализация операции dynamic_cast весьма эффективна, поскольку ссылка на информацию о типе объекта заносится в таблицу виртуальных
методов, и доступ к ней осуществляется легко.
С точки зрения логики требование, чтобы объект был полиморфным, также оправдано:
ведь если класс не имеет виртуальных методов, его нельзя безопасным образом использовать, не зная точный тип указателя. А если тип известен, использовать операцию dynamic_cast нет необходимости. Результат примепения операции dynamic_cast к указателю всегда требуется проверять явным образом. В приведенном ниже примере описан полиморфный базовый
класс В и производный от него класс С, в котором определена функция f2. Для того, чтобы вызывать ее из функции demo только в случае, когда последней передается указатель на объект производного класса, используется операция
dynamic_cast с проверкой результата преобразования:
#include <iostream.h>
#include <typeinfo.h>
class B{
public: virtual void fl () { };
};
class C: public B{
public: void f2(){cout «"f2":};
};
void demo(6* p){
C* с = dynamic_cast<C*>(p);
if (c) c->f2();
else cout «"Передан не класс С";
}
int main(){
В* b = new В;
demo(b); // Выдается сообщение "Передан не класс С"
С* с - new С;
demo(c); // Выдается сообщение "f2" (правильно)
Return 0;
}
При использовании в этом примере вместо dynamic_cast приведения типов в стиле
С, например:
С* с = (С*) р;
проконтролировать допустимость операции невозможно, PI если указатель р на самом деле не ссылается на объект класса С, это приведет к ошибке. Другим недостатком приведения в стиле С является невозможность преобразования
в производный виртуального базового класса, это запрещено синтакси чески. С помощью операции dynamic_cast такое преобразование возможно при
условии, что класс является полиморфным и преобразование недвусмыслерню. Рассмотрим пример, в котором выполняется понижающее преобразование виртуального
базового класса:
#include <iostream.h>
#include <typeinfo.h>
class A{
public: virtual ~A(){};}
c]ass B: public virtual A{};
class C: public virtual A{};
class D: public B. public C{};
void demo(A *a){
D* d = dynamic_cast<D*>(a);
i f (d) {... }
/ / A
/ / / \
/ / В С
/ / \ /
/ / D
int main(){
D *d = new D; demo(d);
Return 0;
}
Повыщающее преобразование