cout << "\n\n";
if(typeid(i) == typeid(j))
cout << "Типы переменных i и j одинаковы.\n";
if(typeid(i) != typeid(f))
cout << "Типы переменных i и f неодинаковы.\n";
return 0;
}
При выполнении этой программы получены такие результаты.
Тип переменной i: int
Тип переменной f: float
Тип переменной ob: class myclass
Типы переменных i и j одинаковы.
Типы переменных i и f неодинаковы.
Если оператор typeid применяется к указателю на полиморфный базовый класс (вспомните: полиморфный класс — это класс, который содержит хотя бы одну виртуальную функцию), он автоматически возвращает тип реального объекта, на который тот указывает: будь то объект базового класса или объект класса, выведенного из базового.
Следовательно, оператор typeid можно использовать для динамического определения типа объекта, адресуемого указателем на базовый класс. Применение этой возможности демонстрируется в следующей программе.
/* Пример применения оператора typeid к иерархии полиморфных классов.
*/
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
virtual void f() {}; // делаем класс Base полиморфным
// . . .
};
class Derived1: public Base {
// . . .
};
class Derived2: public Base {
// ...
};
int main()
{
Base *p, baseob;
Derived1 ob1;
Derived2 ob2;
p = &baseob;
cout << "Переменная p указывает на объект типа ";
cout << typeid(*p).name() << endl;
p = &ob1;
cout << "Переменная p указывает на объект типа ";
cout << typeid(*p).name() << endl;
p = &ob2;
cout << "Переменная p указывает на объект типа ";
cout << typeid(*p).name() << endl;
return 0;
}
Вот как выглядят результаты выполнения этой программы:
Переменная р указывает на объект типа Base
Переменная р указывает на объект типа Derived1
Переменная р указывает на объект типа Derived2
Если оператор typeid применяется к указателю на базовый класс полиморфного типа, тип реально адресуемого объекта, как подтверждают эти результаты, будет определен во время выполнения программы.
Во всех случаях применения оператора typeid к указателю на неполиморфную иерархию классов будет получен указатель на базовый тип, т.е. то, на что этот указатель реально указывает, определить нельзя. В качестве эксперимента превратите в комментарий виртуальную функцию f() в классе Base и посмотрите на результат. Вы увидите, что тип каждого объекта после внесения в программу этого изменения будет определен как Base, поскольку именно этот тип имеет указатель p.
Поскольку оператор typeid обычно применяется к разыменованному указателю (т.е. к указателю, к которому уже применен оператор "*"), для обработки ситуации, когда этот разыменованный указатель оказывается нулевым, создано специальное исключение. В этом случае оператор typeid генерирует исключение типа bad_typeid.
Ссылки на объекты иерархии полиморфных классов работают подобно указателям. Если оператор typeid применяется к ссылке на полиморфный класс, он возвращает тип объекта, на который она реально ссылается, и это может быть объект не базового, а производного типа. Описанное средство чаще всего используется при передаче объектов функциям по ссылке. Например, в следующей программе функция WhatType() объявляет ссылочный параметр на объекты типа Base. Это значит, что функции WhatType() можно передавать ссылки на объекты типа Base или ссылки на объекты любых классов, производных от Base. Оператор typeid, примененный к такому параметру, возвратит реальный тип объекта, переданного функции.