Вопросы по RTTI
От: Dima2  
Дата: 24.01.02 10:37
Оценка: 6 (3)
class X
{
    virtual void func() {};
};

class XX : public X {};

void main()
{
    XX *xx = new XX();

    X *x = dynamic_cast<X*>(xx);

    const type_info &tiXX = typeid(xx);
    const type_info &tiX  = typeid(x);

    XX *xx1 = dynamic_cast<XX*>(x);        // ???

    delete xx;
}


Попробую сформулировать вопросы.

При восходящем приведении (от производного к базовому) все в порядке.
    X *x = dynamic_cast<X*>(xx);

И если посмотреть в дизассемблере, то собственно RTTI для такого
приведения не требуется. Переменной 'x' тупо присваивается значение
переменной 'xx'

А вот при нисходящем уже требуется RTTI, и компилятор предупреждает
что в этой строке
    XX *xx1 = dynamic_cast<XX*>(x);        // ???

используется dynamic_cast с полиморфичным классом при отключенной
опции /GR-. Включаем эту /GR и все в порядке. В MSDN написано что
эта опция позволяет компилятору добавлять код для проверки типа
объекта в рантайме.


И собственно вопросы:
1. Почему нормально работает оператор 'typeid' даже при отключенной
опции GR, что для 'typeid' не требуется RTTI
    const type_info &tiXX = typeid(xx);
    const type_info &tiX  = typeid(x);


2. Где живет эта информация об RTTI. В таблице виртуальных ф-ий что-то
не увидел я указателя на RTTI. Хотя это вопрос реализации, но все же
интересно.

3. Добавляется ли эта RTTI ко всем полиморфным классам программы или
только к классам, которые используются в dynamic_cast
Re: Вопросы по RTTI
От: Dancom Украина  
Дата: 24.01.02 14:12
Оценка: 2 (1)
Хмм....

На третий вопрос с ходу:
Страуструп писал что при включенном RTTI — инфа ДОЛЖНА вставляться в каждый полиморфный класс.

Дальше — при выключенном RTSP VC6 на typeinfo показывает
offset XX * `RTTI Type Descriptor' (00427c58)
а по адресу идет что-то подозрительно похожее на сигнатуру 28 50 42 00
потом 4 нуля и какие-то данные

а хранит оно пойнтер на RTTI видимо общую таблицу последней записью в vtable.А там берется пойнтер на реальную RTTI запись.

Видимо RTTI инфа включаеться всегда (в случае использования) а ключ — просто для предупреждения ИМХО.

Кто знает точно — отзовитесь.

D>Попробую сформулировать вопросы.


D>При восходящем приведении (от производного к базовому) все в порядке.

D>
D>    X *x = dynamic_cast<X*>(xx);
D>

D>И если посмотреть в дизассемблере, то собственно RTTI для такого
D>приведения не требуется. Переменной 'x' тупо присваивается значение
D>переменной 'xx'

D>А вот при нисходящем уже требуется RTTI, и компилятор предупреждает

D>что в этой строке
D>
D>    XX *xx1 = dynamic_cast<XX*>(x);        // ???
D>

D>используется dynamic_cast с полиморфичным классом при отключенной
D>опции /GR-. Включаем эту /GR и все в порядке. В MSDN написано что
D>эта опция позволяет компилятору добавлять код для проверки типа
D>объекта в рантайме.


D>И собственно вопросы:

D>1. Почему нормально работает оператор 'typeid' даже при отключенной
D> опции GR, что для 'typeid' не требуется RTTI
D>
D>    const type_info &tiXX = typeid(xx);
D>    const type_info &tiX  = typeid(x);
D>


D>2. Где живет эта информация об RTTI. В таблице виртуальных ф-ий что-то

D> не увидел я указателя на RTTI. Хотя это вопрос реализации, но все же
D> интересно.

D>3. Добавляется ли эта RTTI ко всем полиморфным классам программы или

D> только к классам, которые используются в dynamic_cast
Re[2]: Вопросы по RTTI
От: Dima2  
Дата: 24.01.02 16:38
Оценка:
Здравствуйте Dancom, Вы писали:

D>На третий вопрос с ходу:

D>Страуструп писал что при включенном RTTI — инфа ДОЛЖНА вставляться в каждый полиморфный класс.

Страуструп микрософту не указ.

D>Видимо RTTI инфа включаеться всегда (в случае использования) а ключ — просто для предупреждения ИМХО.

Да нет, не просто для предупреждения в том то и дело. Предупреждение выдает не напрасно, в этом месте программа вылетает в исключение.
Re: Вопросы по RTTI
От: Dima2  
Дата: 24.01.02 18:34
Оценка:
Здравствуйте Dima2, Вы писали:

Что то не пойму дизассемблерный код этой строки
    XX *xx1 = dynamic_cast<XX*>(x);

в обоих случаях (с /GR и /GR-) вроде бы одинаковый и структуры `RTTI Type Descriptor' тоже, но в одном случае вылетает исключение в другом нет.
Re[2]: Вопросы по RTTI
От: Dima2  
Дата: 25.01.02 15:01
Оценка:
Здравствуйте Dima2, Вы писали:

D>Здравствуйте Dima2, Вы писали:


D>Что то не пойму дизассемблерный код этой строки

D>
D>    XX *xx1 = dynamic_cast<XX*>(x);
D>

D>в обоих случаях (с /GR и /GR-) вроде бы одинаковый и структуры `RTTI Type Descriptor' тоже, но в одном случае вылетает исключение в другом нет.

Так не пойдет, выкинули на вторую страницу
Re[2]: Вопросы по RTTI
От: Dima2  
Дата: 28.01.02 14:57
Оценка: 10 (2)
Здравствуйте Dima2, Вы писали:

От нечего делать разобрался в этом вопросе.

Во первых где живет RTTI. Указатель на таблицу RTTI располагается до таблицы виртуальных функций объекта (т.е. до указателей на виртуальные ф-ии). Таблица RTTI представляет из себя 4..5 указателей, один из них указатель на
'RTTI Type Descriptor', остальные у меня оказались нулевыми, возможно зарезервированы для на будущее или еще для чего.

'RTTI Type Descriptor' это также таблица, в которой собственно и содержится описание класса данного объекта. Описание класса не что иное как обычная строка имени класса (правда немного завернутая), например ".РAVXX@@" (где XX имя класса)

Для операторов 'typeid' и 'dynamic_cast' таблицы 'RTTI Type Descriptor' одинаковые (почти).
Когда мы вызываем оператор 'typeid(xx)' собственно мы получаем адрес этой
'RTTI Type Descriptor'. Ф-я 'raw_name' (класса type_info) возвращает нам указатель на неочищенное имя класса (".РAVXX@@"), ф-я же 'name' очищает это имя и возвращает что-то типа "Class XX*".

Теперь что же делает опция /GR.
Именно она записывает указатель на таблицу RTTI в каждый экземпляр объекта (до виртульных ф-ий). Если опция не включена, то на это место записывается 0x00000000 и когда оператор 'dynamic_cast' пытается получить адрес RTTI, то он обращается по адресу 0x00000000 и естественно вылетает в исключение.

И как правильно сказал Dancom RTTI записывается в каждый полиморфный класс. В не полиморфный не записывается, т.к. нет таблицы виртуальных ф-ий, да собственно смысла применять RTTI для такого класса нет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.