Операция static_cast используется для преобразования типа на этапе компиляции

между:

• целыми типами;

• целыми и вещественными типами;

• целыми и перечисляемыми типами;

• указателями и ссылками на объекты одной иерархии, при условии, что оно однозначно и не связано с понижающим преобразованием виртуального базового класса.

 

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;

}

Повыщающее преобразование