Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> RTTI 
:(
    Опции темы
mes
Дата 31.10.2009, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата

    
Цитата

нельзя примянять к объектам таких классов динамик_каст

это не верно.

хотелось бы уточнить что не верно ..

под фразой "нельзя применять"  подразумевалось, что нельзя получить ожидаемый (т.е такой какой был бы в случае обладания классом виртуальной функции) результат,
а не то что применение каста вызовет ошибку компиляции либо рантайма.. Т.е. "нельзя" в роли "бесполезно", a не "невозможно" или "строжайше запрещено" smile

все еще неверно ? 

или речь про это ?
Цитата
 соответственно виртуальная таблица не создастся, правильно??
Цитата
 да, по этой самой причине нельзя 

т.е. то что отсутствие именно виртуальной таблицы упоминается как причина ?


P.S.по-мойму форум глючит .. старые темы с новыми датами всплыли.. и комменты некоторые почему то изменились.. 



Это сообщение отредактировал(а) mes - 31.10.2009, 21:28


--------------------
PM MAIL WWW   Вверх
UnrealMan
Дата 1.11.2009, 01:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(mes @  31.10.2009,  21:15 Найти цитируемый пост)
хотелось бы уточнить что не верно ..

Чтобы говорить о требованиях к операнду dynamic_cast и внутренней реализации преобразования, надо бы уточнить, какое именно преобразование рассматривается (а в случае с реализаций ещё и компиляторы). dynamic_cast не всегда использует RTTI.
PM MAIL   Вверх
mes
Дата 1.11.2009, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(UnrealMan @  1.11.2009,  00:16 Найти цитируемый пост)
Чтобы говорить о требованиях к операнду dynamic_cast и внутренней реализации преобразования, надо бы уточнить, какое именно преобразование рассматривается (а в случае с реализаций ещё и компиляторы). dynamic_cast не всегда использует RTTI. 


A..ну теперь вроде понятно что куда Вы клоните..Перечитал тему еще раз - действительно выглядит не связано..
Попробую расставить на свои места :
 Вначале я думал что топикстартера интересует :
Цитата(Graf_h @  24.9.2009,  21:38 Найти цитируемый пост)
Как в иерархии наследования компилятор знает родителей 


ответом было :
Цитата(mes @  25.9.2009,  10:42 Найти цитируемый пост)
 Программист определяет тип объекту, а компилятор его ассоциативно запоминает или выводит из имеющихся  данных.... потому что программист указал это : class Derived: public Base {};

после, заметив слово "RTTI" в названии, я предположил что интересует обратное преобразование (т.е. downcast), потому как для приведенного в примере информации достаточно и на этапе компиляции.. Но явно я забыл это указать, (если быть точнее я не хотел запутывать тс еще больше), сократив мысль до такой :
Цитата(mes @  25.9.2009,  10:42 Найти цитируемый пост)
Посмотрел на название темы RTTI, значит интересует dynamic_cast ?

и в дальнейшем dynamic_cast подразумевался именно как инструмент downcasta.

Теперь попытаюсь исправить те два вранья :
Цитата(mes @  25.9.2009,  21:07 Найти цитируемый пост)
да, по этой самой причине нельзя применять к объектам таких (не обладающих не одним виртуальным методом) классов динамик_каст.

следует читать : нельзя произвести  downcast  с проверкой рантайма к объектам таких классов.. 
сам же dynamic_cast однако можно использовать для их (объектов) upcasta и crosscasta.

Цитата(mes @  25.9.2009,  21:07 Найти цитируемый пост)
находится ли указатель на ВMТ в нужном списке наследования и если нет, то вернуть ноль, это и делает dynamic_cast.
следует дополнить : при downcaste.

Естественно  само описание с участием ВМТ используются условно как частный случай реализации.

UnrealMan, я правильно понял, что Вы имели ввиду ?


Это сообщение отредактировал(а) mes - 1.11.2009, 14:33


--------------------
PM MAIL WWW   Вверх
UnrealMan
Дата 1.11.2009, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(mes @  1.11.2009,  14:16 Найти цитируемый пост)
и в дальнейшем dynamic_cast подразумевался именно как инструмент downcasta

RTTI может ещё использоваться для crosscast'а и приведения к void*. Для upcast'а RTTI не нужна.

Цитата(mes @ 1.11.2009,  14:16)
Цитата(mes @  25.9.2009,  21:07 Найти цитируемый пост)
находится ли указатель на ВMТ в нужном списке наследования и если нет, то вернуть ноль, это и делает dynamic_cast.
следует дополнить : при downcaste.

А если мы к ссылке приводим, то в этом случае тоже нулевой указатель может возвращаться? smile

P.S.
А-а-а, мне запретили рейтинговать smile  Ну всё, теперь я могу открыто сказать, что этот форум по C++ полное гов­но. Больше мне нет смысла сюда приходить, а вам счастливо оставаться в этом быдлятнике  smile 

Это сообщение отредактировал(а) UnrealMan - 1.11.2009, 16:37
PM MAIL   Вверх
mes
Дата 1.11.2009, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(UnrealMan @  1.11.2009,  15:19 Найти цитируемый пост)
RTTI может ещё использоваться для crosscast'а и приведения к void*.

спасибо, этого не знал и даже не подозревал.. Надо будет покапать в этом направлении..

Цитата(UnrealMan @  1.11.2009,  15:19 Найти цитируемый пост)
А если мы к ссылке приводим, то в этом случае тоже нулевой указатель может возвращаться? smile

В предыдущем посте я пытался донести, что обсуждении с тс было посвящено не возможностям  dynamic_cast и требований к этому оператору, более того сам dynamic_cast имел отношение к разговору только лишь потому, что является инструментом для некоторых преобразований.. А обсуждалось каким образом компилятор может узнать о возможности правильного преобразования одного типа к другому (в том числе и в рантайме).

А так я в курсе, что неудачный dynamic_cast для ссылки возбуждает исключение.  smile 







--------------------
PM MAIL WWW   Вверх
DrHex
Дата 2.11.2009, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 2.5.2009

Репутация: нет
Всего: нет



Книжная теория это всего лишь слова. 
Пример vs2008


Код

class A
{
public :
    virtual void func1() = 0;

private:
    int someField;
};

class B
{
public :
    virtual void func2()
    {
        printf("Hello from B\n");
    }

private:
    int someField;
};

class C : public A, public B
{
public :
    void func1()
    {
        printf("Hello from AC\n");
    }

    void func2()
    {
        printf("Hello from BC\n");
    }
};

int main(int argc, _TCHAR* argv[])
{
    C * c = new C();
    A* a = dynamic_cast<A*>(c);
    a->func1();

    B* b = dynamic_cast<B*>(c);    
    b->func2();

    return 0;



На выходе в релизной версии имеем
Код

00401030 56               push        esi  
00401031 6A 10            push        10h  
00401033 E8 46 00 00 00   call        operator new (40107Eh) 
00401038 83 C4 04         add         esp,4 
0040103B 85 C0            test        eax,eax 
0040103D 74 18            je          main+27h (401057h) 
0040103F C7 40 08 30 21 40 00 mov         dword ptr [eax+8],offset B::`vftable' (402130h) 
00401046 C7 00 38 21 40 00 mov         dword ptr [eax],offset C::`vftable' (402138h) 
0040104C C7 40 08 40 21 40 00 mov         dword ptr [eax+8],offset C::`vftable' (402140h) 
00401053 8B F0            mov         esi,eax 
00401055 EB 02            jmp         main+29h (401059h) 
00401057 33 F6            xor         esi,esi 
00401059 8B 06            mov         eax,dword ptr [esi] 
0040105B 8B 10            mov         edx,dword ptr [eax] 
0040105D 8B CE            mov         ecx,esi 
0040105F FF D2            call        edx  
00401061 8B 46 08         mov         eax,dword ptr [esi+8] 
00401064 8B 10            mov         edx,dword ptr [eax] 
00401066 8D 4E 08         lea         ecx,[esi+8] 
00401069 FF D2            call        edx  
0040106B 33 C0            xor         eax,eax 
0040106D 5E               pop         esi  
0040106E C3               ret


Для тех кто не понимает

Код

0040103F C7 40 08 30 21 40 00 mov         dword ptr [eax+8],offset B::`vftable' (402130h) 
00401046 C7 00 38 21 40 00 mov         dword ptr [eax],offset C::`vftable' (402138h) 
0040104C C7 40 08 40 21 40 00 mov         dword ptr [eax+8],offset C::`vftable' (402140h) 


Происходит заряд виртуальной таблицы....


Код

00401059 8B 06            mov         eax,dword ptr [esi] 
0040105B 8B 10            mov         edx,dword ptr [eax] 
0040105D 8B CE            mov         ecx,esi 
0040105F FF D2            call        edx


Пырвый вызов функции (a->func1();) Так как указатель на функцию идет первым(dword ptr [eax],offset C::`vftable' (402138h) ) соответственно вызов происходит по указателю(в нашем без смещений от объекта, то и есть кастинг бых выполнен в стиле "С")

Код


00401061 8B 46 08         mov         eax,dword ptr [esi+8] 
00401064 8B 10            mov         edx,dword ptr [eax] 
00401066 8D 4E 08         lea         ecx,[esi+8] 
00401069 FF D2            call        edx


esi+8 смещение на вось байт. Почему на восемь??? указатель на функцию(4 байта) + поле (4 байта) и того восемь. То и есть приведение было в стиле "С" и смещение на восемь байт.

В дебажном варианте тоже не всегда можно удидеть RTTI
Код

004139F3 83 7D F8 00      cmp         dword ptr [c],0 
004139F7 74 0E            je          main+77h (413A07h) 
004139F9 8B 45 F8         mov         eax,dword ptr [c] 
004139FC 83 C0 08         add         eax,8 
004139FF 89 85 0C FF FF FF mov         dword ptr [ebp-0F4h],eax 
00413A05 EB 0A            jmp         main+81h (413A11h) 
00413A07 C7 85 0C FF FF FF 00 00 00 00 mov         dword ptr [ebp-0F4h],0 
00413A11 8B 8D 0C FF FF FF mov         ecx,dword ptr [ebp-0F4h] 
00413A17 89 4D E0         mov         dword ptr [b],ecx 


Ключевой момент(Смещение указателя)
Код

add         eax,8 



Вот другое дело что взять да и убрать public наследование

то и есть меняем 
Код

class C : public A, public B
 
на 
Код

class C :  A,  B


И видем картину
A* a = dynamic_cast<A*>©;
Код

004139ED 6A 00            push        0    
004139EF 68 28 70 41 00   push        offset A `RTTI Type Descriptor' (417028h) 
004139F4 68 14 70 41 00   push        offset C `RTTI Type Descriptor' (417014h) 
004139F9 6A 00            push        0    
004139FB 8B 45 F8         mov         eax,dword ptr [c] 
004139FE 50               push        eax  
004139FF E8 CD D7 FF FF   call        @ILT+460(___RTDynamicCast) (4111D1h) 
00413A04 83 C4 14         add         esp,14h 
00413A07 89 45 EC         mov         dword ptr [a],eax 


___RTDynamicCast
Код

102B32A0 8B FF            mov         edi,edi 
102B32A2 55               push        ebp  
102B32A3 8B EC            mov         ebp,esp 

Стандартный для студии пролог....

Код

102B32AC 68 80 32 2D 10   push        offset _except_handler4 (102D3280h) 
102B32B1 64 A1 00 00 00 00 mov         eax,dword ptr fs:[00000000h] 

Установка SEH(catch)
Код


dword ptr fs:[00000000h],eax 
102B32D2 89 65 E8         mov         dword ptr [ebp-18h],esp

Есче(еще для умных) SEH.
Опистим детали(это же не учебник)

Один из ключевых моментов FindMITargetTypeInstance  должен вернуть указатель на объект
Код

102B3365 E8 26 02 00 00   call        FindMITargetTypeInstance (102B3590h) 
102B336A 83 C4 14         add         esp,14h 
102B336D 89 45 E0         mov         dword ptr [ebp-20h],eax 
102B3370 EB 1F            jmp         __RTDynamicCast+0F1h (102B3391h) 


jmp         __RTDynamicCast+0F1h делает переход на 
Код

cmp         dword ptr [ebp-20h],0 
102B3395 74 1B            je          __RTDynamicCast+112h (102B33B2h) 


Как видим функция должна вернуть не ноль что бы условного переход не было, если условный переход(je          __RTDynamicCast+112h (102B33B2h) ) произойдет, то будет вызвана ошибка(генерация исключения на сколько помню...)  


--------------------
google.com и это все.
PM MAIL   Вверх
Graf_h
Дата 15.4.2010, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

Репутация: 2
Всего: 5



Цитата(mes @  25.9.2009,  22:07 Найти цитируемый пост)
компилятору не нужно знать реальный тип объекта в реале, главное может ли произойти нужное преобразование,
т.е. (для динамик_каста) можно ли привести имеющийся указатель к тому который запросил программист.
В виртуальной таблице (ВMТ) наследника, хранится указатель на ВMТ предка, и этим  образуют "список наследования"
осталось только проверить находится ли указатель на ВMТ в нужном списке наследования и если нет, то вернуть ноль, это и делает dynamic_cast.


mes скажите пожалуйста,  как можно получиь таблицу парента, по текущей вирт таблице. Я как не пыался, не получилось (


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
mes
Дата 15.4.2010, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Graf_h @  15.4.2010,  09:33 Найти цитируемый пост)
 как можно получиь таблицу парента. 

даже наличие таблицы, не говоря о том как она устроена  - implementation defined, а значит вопрос должен как минимум упоминать конкретный компилятор.
ну а если в рамках пользователя С++, то такой вопрос не должен интересовать.

Цитата(Graf_h @  15.4.2010,  09:33 Найти цитируемый пост)
  как можно получиь таблицу парента, по текущей вирт таблице

для этого нужно знать структуру VMT, ну  и по какому смещению она расположена (для нахождения текущей)




--------------------
PM MAIL WWW   Вверх
Graf_h
Дата 15.4.2010, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

Репутация: 2
Всего: 5



Код

ну а если в рамках пользователя С++, то такой вопрос не должен интересовать


Почему? Если, к примеру, мне нужен свой dynamic_cast


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
mes
Дата 15.4.2010, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Graf_h @  15.4.2010,  14:08 Найти цитируемый пост)
Почему? Если, к примеру, мне нужен свой dynamic_cast?  

потому что такое возможно либо узкоспециализированное - под каждый компилятор свое,
либо составлять свою таблицу - такой путь предпочтительней.. 




--------------------
PM MAIL WWW   Вверх
Graf_h
Дата 15.4.2010, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

Репутация: 2
Всего: 5



mes, спасибо smile 


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1005 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.