Механізм rtti (run-time type identification)

..1 Механізм RTTI (run-time type identification)

..1.1 static_cast і покажчики

Неявне приведення покажчика на об'єкт похідного типу до покажчика на об'єкт базового типу компілятор прекрасно виконує сам, так як похідний клас містить повні визначення своїх базових класів => таке підвищує (upcast) приведення типу завжди безпечно!

Вірно і наступне твердження: якщо об'єкт насправді є об'єктом похідного типу, а в нашому розпорядженні є покажчик на базовий клас, то коректним повинно бути і перетворення покажчика "вниз" по ієрархії класів аж до перетворення такого покажчика до покажчика на фактичний (цільової) тип - знижує приведення (downcast).

Для приведення покажчика на базовий тип до покажчика похідного типу призначений оператор явного приведення типу static_cast - це механізм часу компіляції!

// A і b пов'язані спадкуванням

class B: public A

// З - «автономний» клас

B * pB = static_cast(PA); // з точки зору компілятора все коректно, так як класи пов'язані спадкуванням!

// F (d); // помилка компілятора - такого перетворення немає!

F (a); // помилки компілятора немає, але результат некоректний, оскільки насправді об'єкт A, а не B!

Зауваження: компілятор перевіряє тільки той факт, що обидва класи пов'язані з допомогою наслідування => вважає таке приведення коректним. А насправді таке перетворення небезпечно! Тому виникла необхідність в способі перевірки можливості такого перетворення.

Зауваження: static_cast зазвичай використовується для неполіморфних типів (немає віртуальних функцій).

..1.2 Динамічна ідентифікація типу

RTTI характеризується трьома поняттями:

1) оператор dynamic_cast - для перетворення поліморфних типів

2) оператор typeid - для визначення точного (exact) типу об'єкта

3) клас type_info - (це те, що повертає оператор typeid)

..1.3 Для підключення RTTI:

1) в опціях проекту Project \ Properties \ C / C ++ \ Language - включити Enable Run-Time Type info (або / GR)

2) #include

3) механізм працює тільки для поліморфних класів (тобто задіяні таблиці віртуальних функцій)

..1.4 Оператор typeid і клас type_info Мейерс2 - стр132

Ідентифікація типів під час виконання дозволяє отримати інформацію про об'єкти і класах. При цьому для зберігання інформації, яка запитується повинна бути відведена область пам'яті.

1) скільки б об'єктів класу X ми не створювали, досить зберігати інформацію власне про тип X в єдиному екземплярі в кожному класі => для кожного класу компілятор створює структуру даних типу type_info

2) повинен існувати спосіб отримання цієї інформації для кожного об'єкта => доступ до об'єкта type_info можна отримати за допомогою оператора typeid.

3) Що існує в єдиному екземплярі для всіх об'єктів? - static або таблиця віртуальних функцій. У специфікації мови сказано, що отримання цієї інформації гарантується тільки для поліморфних типів (тобто якщо є хоча б одна віртуальна функція). Дані RTTI виконують приблизно ту ж задачу, що і таблиця віртуальних функцій => RTTI була розроблена саме за допомогою віртуальної таблиці класу. Наприклад індекс 0 у таблиці може містити покажчик на об'єкт type_info:

При такій реалізації пам'ять буде витрачатися тільки на додавання ще одного осередку в кожну таблицю віртуальних функцій + виділення пам'яті для зберігання об'єкта type_info для кожного класу.

..1.4.1 Формат type_info

int operator == (const type_info rhs) const;

int operator! = (const type_info rhs) const;

int before (const type_info rhs) const;

const char * raw_name () const; // декорірованноеімя

Основні можливості: 1) перевантажені оператори == і! =.

2) + методи для отримання імені класу.

..1.4.2 Форми оператора typeid:

const type_info typeid (об'єкт) // де в якості об'єкта може виступати вираз, наприклад (* P)

const type_info typeid (тип)