Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
###Cpp_лкц1_1.09_11_#дляБАК#29_01_12.doc
Скачиваний:
40
Добавлен:
29.04.2019
Размер:
6.42 Mб
Скачать

Часть II. Объектно-ориентированное программирование

ПРИМЕЧАНИЕ

Для использования RTTI необходимо подключить к программе заголовочный файл <typeinfo>. Кроме того, необходимо, чтобы был установлен соответствующий режим компилятора.

Для полиморфного объекта реализация операции 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 « nf2":}:

}:

void demo(B* p){

С* с = dynamic_cast<C*>(p);

if (c) c->f2();

else cout « "Передан не класс С":

}

int main(){

В* b » new В:

demo(b): // Выдается сообщение "Передан не класс С"

С* с - new С:

demo(c): // Выдается сообщение "f2" (правильно)

return 0: } При использовании в этом примере вместо dynamic_cast приведения типов в стиле С, например:

С* с = (С*) р:

проконтролировать допустимость операции невозможно, и если указатель р на самом деле не ссылается на объект класса С, это приведет к ошибке.

Другим недостатком приведения в стиле С является невозможность преобразования в производный виртуального базового класса, это запрещено синтакси-

Глава 8. Преобразование типов

235

чески. С помощью операции dynamic_cast такое преобразование возможно при условии, что класс является полиморфным и преобразование недвусмысленно. Рассмотрим пример, в котором выполняется понижающее преобразование виртуального базового класса:

#include <iostream.h> #include <typeinfo.h> class A{

public: virtual ~A(){};} class 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);

if (d) { ... }

int main(){

D *d = new D; demo(d);

return 0; }

Преобразование ссылок

Для аргумента-ссылки смысл операции преобразования несколько иной, чем для указателя. Поскольку ссылка всегда указывает на конкретный объект, операция dynamic_cast должна выполнять преобразование именно к типу этого объекта. Корректность приведения проверяется автоматически, в случае несовпадения порождается исключение bad_cast:

#include <iostream.h> #include <typeinfo.h> class B{

public: virtual void fl(){}:

}:

class C: public B{

public: void f2(){ ... }:

}:

void demo(B& p){

try{

C& с = dynamic_cast<C&>(p); c.f2();

}

catch(bad_cast){

}

}

int main(){ B* b = new

B; demo(*b);

// Порождается исключение

236