Программирование на C и C++

Онлайн справочник программиста на C и C++

Идентификация типа во время исполнения (RTTI)

Используя идентификацию типа времени исполнения (run-time type identification — RTTI) можно определить тип объекта во время исполнения программы. Для этого используется функция typeid. Для использования этой функции необходимо включить заголовочный файл typeinfo.h. Общая форма записи функции typeid имеет следующий вид:

typeid (объект)

Здесь объект является объектом, чей тип требуется определить. Функция typeid возвращает ссылку на объект типа typeinfo, который описывает тип объекта объект. (В проекте стандарта С++ этот тип называется type_info.) Класс typeinfo определяет следующие публичные члены:

bool operator== (const typeinfo &ob) const;
bool operator!= (const typeinfo &ob) const;
bool before(const typeinfo &ob) const;
const char *name() const;

Перегруженные операторы == и != обеспечивают сравнение типов. Функция before() возвращает истину, если вызываемый объект стоит выше в иерархии объектов, чем объект, используемый в качестве параметра. Функция before() предназначена большей частью для внутреннего использо­вания. Возвращаемое ею значение не имеет ничего общего с иерархией классов или наследовани­ем. Функция name() возвращает указатель на имя типа.

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

ПАМЯТКА: Указатель обязательно должен быть разыменован. Следует также установить режим поддержки RTTI в опциях компилятора.

Следующая программа демонстрирует использование функции typeid

// пример использования typeid
#include <iostream.h>
#include <typeinfo.h>
class BaseClass {
int a, b;
virtual void f() {}; // BaseClass полиморфный
};
class Derived1: public BaseClass {
int i, j;
};
class Derived2: public BaseClass {
int k;
};
int main()
{
int i;
BaseClass *p, baseob;
Derived1 ob1;
Derived2 ob2;
// сначала выводится имя встроенного типа
cout << "Typeid of i is ";
cout << typeid(i).name() << endl;
// демонстрация typeid с полиморфными типами
p = &baseob;
cout << "p is pointing to an object of type ";
cout << typeid(*p).name() << endl;
p = &ob1;
cout << "p is pointing to an object of type ";
cout << typeid(*p).name() << endl;
p = &ob2;
cout << "p is pointing to an object of type ";
cout << typeid(*p).name() << endl;
return 0;
}

Программа выдаст следующий результат на экран:

Typeid of i is int
p is pointing to an object of type BaseClass
p is pointing to an object of type Derived1
p is pointing to an object of type Derived2

Как уже отмечалось, применение функции typeid к указателю на базовый класс полиморфного типа позволяет определить фактический тип объекта, на который указывает указатель во время исполнения программы. Поэкспериментируем теперь, закомментировав виртуальную функцию f() в базовом классе, и посмотрим на результат.

RTTI не является тем средством, которое используется всякой программой. Однако при работе с полиморфными типами она позволяет знать тип объекта в любой ситуации.