Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP.doc
Скачиваний:
13
Добавлен:
25.04.2019
Размер:
1.34 Mб
Скачать

Catch ( std::bad_cast & ) { // обработка исключения

}

p->fA(); // это никогда не выполнится

...

В С++, наряду с преобразованием динамических типов имеется возможность выяснения типов выражений непосредственно при выполнении программы (run-time type identification – RTTI). Средства поддержки RTTI описаны в заголовочном файле typeinfo.h. Их основу составляет класс std::type_info, который инкапсулирует информацию о типе объекта и функции для работы с ней. В нем есть, например, функция name, возвращающая строку с именем текущего типа объекта. Имеется также функция before, позволяющая проверить лексикографическую упорядоченность имен двух типов.

Выяснение типа выражения реализуется унарной операцией typeid. Если операция typeid срабатывает без ошибок, то ее результатом является ссылка на константный статический объект класса std::type_info, содержащий информацию о типе операнда (на каждый тип получается уникальный объект type_info, так что сравнение типов можно заменить сравнением адресов этих объектов). Аргументом операции typeid может быть леводопустимое выражение (lvalue), дающее полиморфный класс, а также идентификатор типа; кроме того, аргументом может быть выражение неполиморфного типа. Если аргумент – lvalue полиморфного типа, то typeid определяет текущий динамический тип аргумента. Если же аргумент – идентификатор типа, то результатом является информация о данном типе. Наконец, если аргументом является выражение неполиморфного типа, то typeid определяет его статический тип. Операция typeid может завершиться с ошибкой (например, когда аргумент – разыменованный нулевой указатель); в этом случае выбрасывается исключение класса std::bad_typeid (также определен в файле typeinfo.h).

Приведенный ниже пример показывает различные варианты использования механизма RTTI.

Пример

#include <iostream> // для cout, endl

// иерархия полиморфных классов

class A {

public:

virtual void fA() {}

};

class B: public A {

public:

void fB() {}

};

class C: public B {

public:

void fC() {}

};

class D: public B {

public:

void fD() {}

};

class E: public D {

public:

void fE() {}

};

int main() {

// объекты с различными модификаторами

C c;

const D d;

volatile E e;

A * pA = &c; // модификация динамического типа

std::cout << "typeid(*pA) = " << typeid(*pA).name() << std::endl

<< "typeid(c) = " << typeid(c).name() << std::endl

<< "typeid(pA) = " << typeid(pA).name() << std::endl;

// выведет:

// typeid(*pA) = C

// typeid(c) = C

// typeid(pA) = A *

pA = const_cast<D*>(&d); // модификация динамического типа

std::cout << "typeid(*pA) = " << typeid(*pA).name() << std::endl

<< "typeid(d) = " << typeid(d).name() << std::endl;

// выведет:

// typeid(*pA) = D

// typeid(d) = D

pA = const_cast<E*>(&e);

std::cout << "typeid(*pA) = " << typeid(*pA).name() << std::endl

<< "typeid(E) = " << typeid(E).name() << std::endl;

// выведет:

// typeid(*pA) = E

// typeid(e) = E

if ( typeid(*pA) == typeid(E) ) {

// условие есть true

std::cout << "typeid(*pA) < typeid(C) == "

<< ( typeid(*pA).before( typeid(C) ) ?

"true" : "false" ) << std::endl;

// выведет: typeid(*pA) < typeid(C) == false

std::cout << "typeid(*pA) > typeid(C) == "

<< ( typeid(C).before( typeid(*pA) ) ?

"true" : "false" ) << std::endl;

// выведет: typeid(*pA) > typeid(C) == true

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]