Название: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 05:57 Есть вот такой незамысловатый header:
Код: #define PQ_OBJECT \ и код: Код: // QObject -> PQWidget вроде написано всё честно и справедливо - PQWidget является потомком QWidget, как и кнопка. И все они после моего наследования имеют поле myList. Код работает. И какой бы виджет я не писал с добавлением макроса PQ_OBJECT, будь то различные кнопки, текстовые поля, контейнеры и... короче, если взять абсолютно любой виджет, он прекрасно преобразуется в PQWidget и не выпендривается :) А вот второй похожий случай: Код: class PQObject; Код: // QObject -> PQObject Все написано в точности так же как и с QWidget. Полная аналогия: PQObject и QTimer - потомки QObject. PQObject и PQTimer имеют поле myList. На этапе преобразования QObject -> PQObject программа работает, но при попытке обратится к какому либо полю из PQ_OBJECT - сегфолт. Ребята, прокомментируйте, пожалуйста, такое поведение? Почему в первом случае код работает, а во втором - нет? Должен ли он вообще был работать или это случайность, которая оказалась случайной для всех виджетов? :) П.с. хочу заметить, что унаследоваться от PQObject , как по идее и должно было быть, я не могу, потому что Qt не допускает двойное наследование Q_OBJECT, а мой PQObject обязательно должен быть наследником QObject. П.п.с. макрос обрезал для читаемости, на самом деле в нем намного больше полей и методов и все они доступны (проверено) при приведении к PQWidget. Название: Re: Приведение к типу Отправлено: Igors от Сентябрь 04, 2015, 11:07 Код: QObject *timer = new PQTimer; Цитировать VMT поля QObject PQObject (myList) Для PQTimer Цитировать VMT Поэтому работать не должно, т.к. myList сидит по разным смещениям. Почему работает для PQPushButton - не знаю, возможно нет полей QPushButton (хранит все в "d"). В любом случае затея с PQObject (Widget) некорректна, надо использовать множественное наследование и потом кросс-приводитьсяполя QObject поля QTimer PQObject (myList) Название: Re: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 11:14 А что это за вывод вы привели? Что за VMT?
Название: Re: Приведение к типу Отправлено: Igors от Сентябрь 04, 2015, 11:17 А что это за вывод вы привели? Что за VMT? Это формат объектов в памяти, VMT - указатель на таблицу виртуаловEdit: есть же простой способ проверить! Код
Название: Re: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 11:23 Это формат объектов в памяти, VMT - указатель на таблицу виртуалов Мне больше интересно как вы это сообщение получили :) как мне самому это все увидеть? Первый раз о таком слышу ^_^надо использовать множественное наследование Я не могу сообразить как корректно организовать множественное наследование из-за ограничений Qt: нельзя дважды наследовать Q_OBJECT. PQObject мне нужен как обертка над QObject, PQTimer как обертка над QTimer и т.д. их много. И у всех должны быть методы или поля именно PQObject'a, поэтому пришлось выкручиваться через макросы. А PQObject должен наследоваться от QObject, иначе нет доступа к метасистеме Qt... в обещем раскрутить этот клубок у меня не получается. Название: Re: Приведение к типу Отправлено: Racheengel от Сентябрь 04, 2015, 11:29 Не, множественное наследование не прокатит из-за Q_OBJECT. Надо теплейтами делать.
Название: Re: Приведение к типу Отправлено: Igors от Сентябрь 04, 2015, 11:34 Мне больше интересно как вы это сообщение получили :) как мне самому это все увидеть? Первый раз о таком слышу ^_^ Создайте экземпляр класса и посмотрите его в отладчикеЯ не могу сообразить как корректно организовать множественное наследование из-за ограничений Qt: нельзя дважды наследовать Q_OBJECT. PQObject мне нужен как обертка над QObject, PQTimer как обертка над QTimer и т.д. их много. И у всех должны быть методы или поля именно PQObject'a, поэтому пришлось выкручиваться через макросы. А PQObject должен наследоваться от QObject, иначе нет доступа к метасистеме Qt... в обещем раскрутить этот клубок у меня не получается. Код Теперь напр в какой-то ф-ции Вы имеете только PQObject Код
Название: Re: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 11:40 Ну это понятно! Только кроме PQTimer мне нужен еще и сам PQObject со всеми плюшками Q_OBJECT'a...
Код: // есть не только такой код: Если я создам структуру не унаследованную от QObject, то я не смогу получить доступ к метасистеме для обычного QObject или QWidget - вот в чем проблема ??? Название: Re: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 11:50 Информация в отладчике очень противоречивая :/
как видно, и у QObject *timer, и у PQObject *ptimer поле myList существует... (http://s019.radikal.ru/i602/1509/e4/b7e8a4438f81.png) Название: Re: Приведение к типу Отправлено: Igors от Сентябрь 04, 2015, 12:06 Ну это понятно! Только кроме PQTimer мне нужен еще и сам PQObject со всеми плюшками Q_OBJECT'a... Это популярное заблуждение. "Ах, нельзя делать множ наследование от QObject! Вот если б не было такого ограничения....". Предположим это так, и, (о чудо!) это разрешено. И мы бодро пишем напрКод: // есть не только такой код: Если я создам структуру не унаследованную от QObject, то я не смогу получить доступ к метасистеме для обычного QObject или QWidget - вот в чем проблема ??? Код Но как это должно работать? Мы сможем связать сигнал или со слотом QWidget или QTimer. Все тоже для мета-системы - или один базовый класс или другой. И, получив сигнал, нам все равно нужно ломиться из одного базового в другой. Какой же "выйгрыш"? Да никакого, зато новых забот полно - ведь "просто так" уже не законнектиться В общем, "продумывайте архитектуру". Напр никто не мешает сделать так Код Да, в методах MyData придется кросс-приводиться, но это не смертельно. Название: Re: Приведение к типу Отправлено: Igors от Сентябрь 04, 2015, 12:15 Информация в отладчике очень противоречивая :/ Создайте "чистый" (new PQObject) и его смотрите - у него нет полей таймера. А поскольку Вы привели "в стиле С" то смещение myList будет вычисляться как для PQObjectкак видно, и у QObject *timer, и у PQObject *ptimer поле myList существует... Название: Re: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 12:49 И мы бодро пишем Уж не знаю как вы так бодро пишете, но вот такое никогда не скомпилируется: Код: class PQObject : public QObject { Получается мне придется создавать PQObject: Код: PQObject *button = new PQPushButton; Название: Re: Приведение к типу Отправлено: wxmaper от Сентябрь 04, 2015, 12:55 а его я уже никуда не смогу пропихнуть... ооо какую же я фигню сморозил :)) PQObject пре-прекрасно кастуется в QObject! :D Да я еще и Q_OBJECT везде совал, а он нужен только PQObject'y... да уж! Спасибо вам, Igors, вы меня спасли от жутких макросов и в корне неверных кастов :))) Самое печальное в этой ситуации то, что проблема вылезла когда проект вырос до размеров огромного неповоротливого слона... таких объектов у меня примерно штук 30-40 %( буду исправлять |