С++ для начинающих



     На redkiekamni.ru карнеол. |     

Оператор typeid - часть 2


class Derived : public Base { /* нет виртуальных функций */ };

Derived dobj;

Base *pb = &dobj;

cout << typeid( *pb ).name() << endl;  // печатается: Base

Операнд typeid имеет тип Base, т.е. тип выражения *pb. Поскольку в классе Base нет виртуальных функций, результатом typeid будет Base, хотя объект, на который указывает pb, имеет тип Derived.

Результаты, возвращенные оператором typeid, можно сравнивать. Например:

#include <typeinfo>

employee *pe = new manager;

employee& re = *pe;

if ( typeid( pe ) == typeid( employee* ) )  // истинно

   // что-то сделать

/*

if ( typeid( pe ) == typeid( manager* ) )   // ложно

if ( typeid( pe ) == typeid( employee ) )   // ложно

if ( typeid( pe ) == typeid( manager )  )   // ложно

*/

Условие в инструкции if сравнивает результаты применения typeid к операнду, являющемуся выражением, и к операнду, являющемуся именем типа. Обратите внимание, что сравнение

typeid( pe ) == typeid( employee* )

возвращает истину. Это удивит пользователей, привыкших писать:

// вызов виртуальной функции

pe->salary();

что приводит к вызову виртуальной функции salary() из производного класса manager. Поведение typeid(pe) не подчиняется данному механизму. Это связано с тем, что pe – указатель, а для получения типа производного класса операндом typeid должен быть тип класса с виртуальными функциями. Выражение typeid(pe) возвращает тип pe, т.е. указатель на employee. Это значение совпадает со значением typeid(employee*), тогда как все остальные сравнения дают ложь.

Только при употреблении выражения *pe в качестве операнда typeid результат будет содержать тип объекта, на который указывает pe:

typeid( *pe ) == typeid( manager )    // истинно

typeid( *pe ) == typeid( employee )   // ложно

В этих сравнениях *pe – выражение типа класса, который имеет виртуальные функции, поэтому результатом применения typeid будет тип адресуемого операндом объекта manager.

Такой оператор можно использовать и со ссылками:

typeid( re ) == typeid( manager )     // истинно

typeid( re ) == typeid( employee )    // ложно

typeid( &re ) == typeid( employee* )  // истинно

typeid( &re ) == typeid( manager* )   // ложно

В первых двух сравнениях операнд re имеет тип класса с виртуальными функциями, поэтому результат применения typeid содержит тип объекта, на который ссылается re. В последних двух сравнениях операнд &re имеет тип указателя, следовательно, результатом будет тип самого операнда, т.е. employee*.

На самом деле оператор typeid возвращает объект класса типа type_info, который определен в заголовочном файле <typeinfo>. Интерфейс этого класса показывает, что можно делать с результатом, возвращенным typeid. (В следующем подразделе мы подробно рассмотрим этот интерфейс.)




Содержание  Назад  Вперед