Название: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 26, 2010, 12:31 Добрый день
Сегодня поплатился за свое пренебрежение ко всяким _cast. Код Это не вылетает, не ведет к утечкам, но.. count возвращается неправильный. А так все хорошо, правильный Код И как такое может быть? :) Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: BRE от Ноябрь 26, 2010, 12:42 А как что определено?
Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 26, 2010, 12:49 А как что определено? Ну так неинтересно - используют dynamic_cast многие (если не все) вот пусть и приведут пример когда оно не равно C приведению :) (это вопрос для начинающих)Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: zenden от Ноябрь 26, 2010, 13:20 Что-то не могу догадаться. Ясно, что это какие-то хитросплетения наследования, механизма виртуальных функций.
Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: RedDog от Ноябрь 26, 2010, 14:03 Что-то не могу догадаться. Ясно, что это какие-то хитросплетения наследования, механизма виртуальных функций. когда, допустим, аргументом некой ф-цци является некий базовый класс, а в зависимости от конкретного переданного типа (наследников базового) выполняются разные условия.Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 26, 2010, 14:31 когда, допустим, аргументом некой ф-цци является некий базовый класс, а в зависимости от конкретного переданного типа (наследников базового) выполняются разные условия. "Некой..некий" - а можно проще или, еще лучше, на примере? СпасибоНазвание: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: pastor от Ноябрь 26, 2010, 14:53 Былобы неплохо увидеть иерархию классов и где и как объявлен NumberOfChildren(). Да, и объектом какого класса может быть translator?
Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: RedDog от Ноябрь 26, 2010, 15:44 когда, допустим, аргументом некой ф-цци является некий базовый класс, а в зависимости от конкретного переданного типа (наследников базового) выполняются разные условия. "Некой..некий" - а можно проще или, еще лучше, на примере? СпасибоКод: void on_click(QWidget *clickedWidget) Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 26, 2010, 16:39 Код: ... Былобы неплохо увидеть иерархию классов и где и как объявлен NumberOfChildren(). Да, и объектом какого класса может быть translator? NumberOfChildren - виртуальный метод. Переменная translator указатель на объект типа CTranslator, который является потомком CMaterialTarget. Правда, есть еще одна маленькая деталь (из-за которой нельзя приводить по-народному)...Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: RedDog от Ноябрь 26, 2010, 16:48 Кастится не от QPushButton, а от их общего базового класса QWidget
Код: void on_click(QWidget *clickedWidget) Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: pastor от Ноябрь 26, 2010, 17:57 NumberOfChildren - виртуальный метод. Переменная translator указатель на объект типа CTranslator, который является потомком CMaterialTarget. Правда, есть еще одна маленькая деталь (из-за которой нельзя приводить по-народному)... А какой тип наследования? (public, protected, ...) Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 27, 2010, 13:42 Кастится не от QPushButton, а от их общего базового класса QWidget То ясно, просто после каста указатели должны сбиваться. Против Вашего примера я не возражаю, конечно если я приведу QTextEdit к QPushButton - то вылетит. Но если виджет QTextEdit, то прямое приведение имеет тот же эффект что и dynamic_cast (в Вашем примере). Интересен случай когда 2 приведения возвращают разные (ненулевые) указателиА какой тип наследования? (public, protected, ...) В оригинале был "virtual public". Я попробовал просто "public" - результат тот жеНазвание: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: RedDog от Ноябрь 27, 2010, 22:35 Кастится не от QPushButton, а от их общего базового класса QWidget То ясно, просто после каста указатели должны сбиваться. Против Вашего примера я не возражаю, конечно если я приведу QTextEdit к QPushButton - то вылетит. Но если виджет QTextEdit, то прямое приведение имеет тот же эффект что и dynamic_cast (в Вашем примере). Интересен случай когда 2 приведения возвращают разные (ненулевые) указателиА какой тип наследования? (public, protected, ...) В оригинале был "virtual public". Я попробовал просто "public" - результат тот жеНазвание: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: ufna от Ноябрь 27, 2010, 23:17 Ну приведение "сишное" будет в статической сборке падать на ура :)
QObject'а потомков так не следует. А если еще добавить интерфейсы в наследование кутэшные, то там вообще веселье с кастами начинается. Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Авварон от Ноябрь 28, 2010, 03:16 Igors
Да хоспади, наследование от 2х виртуал классов - сишный каст не меняет значение указателей, а для динамик каст адрес 2го класса == адрес базы + сайзов(1го). И как бы ваши задачки достали:) Напоролись на что-то - выкладывайте сразу ответ. А то я 5 минут плевался о том что "делать мне больше нечего" и 1 минуту думал вам решение. Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: zenden от Ноябрь 28, 2010, 12:37 Авварон
приведите, пожалуйста, работающий код Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Авварон от Ноябрь 28, 2010, 12:59 zenden
Я не тестил, но по идее что-то типа: Код: class Base Происходит так потому что, скорее всего, указатель на vtable один, а втейблы от 2х классов просто склеиваются. При динамик касте оффсет на 2й втейбл считается адекватно, а при сишном не считается вообще. Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 28, 2010, 16:36 Напоролись на что-то - выкладывайте сразу ответ. А то я 5 минут плевался о том что "делать мне больше нечего" и 1 минуту думал вам решение. Ну я ж предупредил - вопрос для начинающих. А от сразу выложенного ответа немного толку - все так много знают ... :)Ваш код правильный, но заметим что dynamic_cast может и больше, напр. Код Последнее приведение и было на что я напоролся. Все тоже самое можно и с Base * (вместо Derived *) если Base имеет virtual(ы). Как я понял, dynamiс_cast умеет как-то "запрыгнуть" на "полную" VMT (с каким типом объект создавался) и оттуда уже смотреть. Замечание: (мой) отладчик показывает приведенные указатели одинаковые, но это не так если их напечатать. "С" приведение также меняет указатель, но не всегда удачно :) Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: spectre71 от Ноябрь 28, 2010, 19:18 zenden Я не тестил, но по идее что-то типа: Код: class Base Происходит так потому что, скорее всего, указатель на vtable один, а втейблы от 2х классов просто склеиваются. При динамик касте оффсет на 2й втейбл считается адекватно, а при сишном не считается вообще. Извиняюсь. Не ообратил внимание на: Base *o = new Derived; Но это не потому что у Base нет виртуальных функций, а потому что Base не связана наследованием с IFace1 и IFace2. А вот так все нормально: Код
Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: spectre71 от Ноябрь 28, 2010, 19:22 Как я понял, dynamiс_cast умеет как-то "запрыгнуть" на "полную" VMT (с каким типом объект создавался) и оттуда уже смотреть. Замечание: (мой) отладчик показывает приведенные указатели одинаковые, но это не так если их напечатать. "С" приведение также меняет указатель, но не всегда удачно :) Это просто ошибка! IFace1 *o3 = dynamiс_cast <IFace1*> (o2); Пытаемся приводить IFace2 к IFace1. Какой в этом смысл? Они не связаны отношением наследования. Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 28, 2010, 19:42 Все в данном примере нормально. Никаких fail не может быть. Ну не надо так придираться к мелочам - идея совершенно правильная :) Рухнет если Base будет иметь хотя бы 1 член данных. Если же Base будет иметь virtual - то имеем тяжелые ошибки на выполнении. А без virtual компилятор не позволит написать dynamic_cast<Base *>Это просто ошибка! Не связаны. Но если оба базовые классы, то можно перескочить с o1 на o2 и обратно через dynamic_cast (этого я не знал :)). И получить указатель на наследующий класс (Derived *) тоже можно.IFace1 *o3 = dynamiс_cast <IFace1*> (o2); Пытаемся приводить IFace2 к IFace1. Какой в этом смысл? Они не связаны отношением наследования. Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: spectre71 от Ноябрь 28, 2010, 19:53 Не связаны. Но если оба базовые классы, то можно перескочить с o1 на o2 и обратно через dynamic_cast (этого я не знал :)). И получить указатель на наследующий класс (Derived *) тоже можно. А зачем так делать? Что за модель данных этого может потребовать? Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Авварон от Ноябрь 28, 2010, 20:01 А вот так все нормально: Не поверите, тут даже касты не нужны)))Код
Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: spectre71 от Ноябрь 28, 2010, 20:08 А вот так все нормально: Не поверите, тут даже касты не нужны)))Код
Согласен! Но в приведенном вами примере и dynamic_cast не поможет - Base не виртуальный. А вот если сделать его виртуальным, то да: dynamic_cast - работает () - не работает Однако никакого смысла прыгать по веткам не вижу! Название: Re: dynamic_cast и просто приведение - в чем разница? Отправлено: Igors от Ноябрь 28, 2010, 20:46 Но в приведенном вами примере и dynamic_cast не поможет - Base не виртуальный. А вот если сделать его виртуальным, то да: Да, но речь идет о таком коде (полагаем что Base виртуальный)dynamic_cast - работает () - не работает Код Это будет работать корректно с dynamic_cast, но не без него Однако никакого смысла прыгать по веткам не вижу! Да я тоже не видел, но пришлось :) Эквивалентно 2 dynamic_cast - взять вмещающий класс и от негонужный базовый |