Russian Qt Forum
Ноябрь 24, 2024, 00:47 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: dynamic_cast и просто приведение - в чем разница?  (Прочитано 11655 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Ноябрь 26, 2010, 12:31 »

Добрый день

Сегодня поплатился за свое пренебрежение ко всяким _cast.

Код
C++ (Qt)
CMaterialTarget * target = (CMaterialTarget *) translator;
int count = target->NumberOfChildren();
 
Это не вылетает, не ведет к утечкам, но.. count возвращается неправильный.
А так все хорошо, правильный
Код
C++ (Qt)
CMaterialTarget * target = dynamic_cast<CMaterialTarget *> (translator);
 
И как такое может быть?  Улыбающийся
Записан
BRE
Гость
« Ответ #1 : Ноябрь 26, 2010, 12:42 »

А как что определено?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Ноябрь 26, 2010, 12:49 »

А как что определено?
Ну так неинтересно - используют dynamic_cast многие (если не все) вот пусть и приведут пример когда оно не равно C приведению  Улыбающийся (это вопрос для начинающих)
Записан
zenden
Гость
« Ответ #3 : Ноябрь 26, 2010, 13:20 »

Что-то не могу догадаться. Ясно, что это какие-то хитросплетения наследования, механизма виртуальных функций.
Записан
RedDog
Гость
« Ответ #4 : Ноябрь 26, 2010, 14:03 »

Что-то не могу догадаться. Ясно, что это какие-то хитросплетения наследования, механизма виртуальных функций.
когда, допустим, аргументом некой ф-цци является некий базовый класс, а в зависимости от конкретного переданного типа (наследников базового) выполняются разные условия.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Ноябрь 26, 2010, 14:31 »

когда, допустим, аргументом некой ф-цци является некий базовый класс, а в зависимости от конкретного переданного типа (наследников базового) выполняются разные условия.
"Некой..некий" - а можно проще или, еще лучше, на примере? Спасибо
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #6 : Ноябрь 26, 2010, 14:53 »

Былобы неплохо увидеть иерархию классов и где и как объявлен NumberOfChildren(). Да, и объектом какого класса может быть translator?
« Последнее редактирование: Ноябрь 26, 2010, 14:55 от pastor » Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
RedDog
Гость
« Ответ #7 : Ноябрь 26, 2010, 15:44 »

когда, допустим, аргументом некой ф-цци является некий базовый класс, а в зависимости от конкретного переданного типа (наследников базового) выполняются разные условия.
"Некой..некий" - а можно проще или, еще лучше, на примере? Спасибо
Код:
void on_click(QWidget *clickedWidget)
{
     QString caption("");
     QTextEdit *edit = dynamic_cast<QTextEdit *>(clickedWidget);
     if (edit)
          caption = edit->toPlainText():
     else
     QBushButton *button = dynamic_cast<QTextEdit *>(clickedWidget);
     if (button)
         caption = button->text();
    MainWindow->setWindowTitle(caption);
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 26, 2010, 16:39 »

Код:
...
     else {
      QPushButton *button = dynamic_cast<QTextEdit *>(clickedWidget);
      if (button)
         caption = button->text();
     }
..
}
Я добавил скобочки (не суть), но здесь до выполнения дело не дойдет - компилятор вякнет что может присвоить один указатель другому, т.к. QPushButton не родитель QTextEdit.

Былобы неплохо увидеть иерархию классов и где и как объявлен NumberOfChildren(). Да, и объектом какого класса может быть translator?
NumberOfChildren - виртуальный метод. Переменная translator указатель на объект типа CTranslator, который является потомком CMaterialTarget. Правда, есть еще одна маленькая деталь (из-за которой нельзя приводить по-народному)...
Записан
RedDog
Гость
« Ответ #9 : Ноябрь 26, 2010, 16:48 »

Кастится не от QPushButton, а от их общего базового класса QWidget

Код:
void on_click(QWidget *clickedWidget)
{
     QString caption("");
     QTextEdit *edit = dynamic_cast<QTextEdit *>(clickedWidget);
     if (edit)
          caption = edit->toPlainText():
     else{
     QBushButton *button = dynamic_cast<QBushButton *>(clickedWidget); // ошибка тут была
     if (button)
         caption = button->text();
    }
    MainWindow->setWindowTitle(caption);
}
подправил код
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #10 : Ноябрь 26, 2010, 17:57 »

NumberOfChildren - виртуальный метод. Переменная translator указатель на объект типа CTranslator, который является потомком CMaterialTarget. Правда, есть еще одна маленькая деталь (из-за которой нельзя приводить по-народному)...

А какой тип наследования? (public, protected, ...)
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Ноябрь 27, 2010, 13:42 »

Кастится не от QPushButton, а от их общего базового класса QWidget
То ясно, просто после каста указатели должны сбиваться. Против Вашего примера я не возражаю, конечно если я приведу QTextEdit к QPushButton - то вылетит. Но если виджет QTextEdit, то прямое приведение имеет тот же эффект что и dynamic_cast (в Вашем примере). Интересен случай когда 2 приведения возвращают разные (ненулевые) указатели

А какой тип наследования? (public, protected, ...)
В оригинале был "virtual public". Я попробовал просто "public" - результат тот же
Записан
RedDog
Гость
« Ответ #12 : Ноябрь 27, 2010, 22:35 »

Кастится не от QPushButton, а от их общего базового класса QWidget
То ясно, просто после каста указатели должны сбиваться. Против Вашего примера я не возражаю, конечно если я приведу QTextEdit к QPushButton - то вылетит. Но если виджет QTextEdit, то прямое приведение имеет тот же эффект что и dynamic_cast (в Вашем примере). Интересен случай когда 2 приведения возвращают разные (ненулевые) указатели

А какой тип наследования? (public, protected, ...)
В оригинале был "virtual public". Я попробовал просто "public" - результат тот же
В моем примере проверяется какого конкретно класса экземпляр был передан в качестве параметра. Т.к. у каждого  класса разные интерфейсы, то если C-style сделать и не проверить, то можно на AV нарваться, т.к. будет доступ к несуществующему методу.
Записан
ufna
Гость
« Ответ #13 : Ноябрь 27, 2010, 23:17 »

Ну приведение "сишное" будет в статической сборке падать на ура Улыбающийся

QObject'а потомков так не следует. А если еще добавить интерфейсы в наследование кутэшные, то там вообще веселье с кастами начинается.
« Последнее редактирование: Ноябрь 28, 2010, 08:12 от ufna » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #14 : Ноябрь 28, 2010, 03:16 »

Igors
Да хоспади, наследование от 2х виртуал классов - сишный каст не меняет значение указателей, а для динамик каст адрес 2го класса == адрес базы + сайзов(1го).
И как бы ваши задачки достали:) Напоролись на что-то - выкладывайте сразу ответ. А то я 5 минут плевался о том что "делать мне больше нечего" и 1 минуту думал вам решение.
« Последнее редактирование: Ноябрь 28, 2010, 03:17 от Авварон » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.092 секунд. Запросов: 23.