Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [QT4] как разорвать связь объектов 
V
    Опции темы
vadiml
Дата 25.11.2007, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



подправленный пример из tutorial (для наглядности):
Код

#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget *widget = new QWidget;
    widget->setFixedSize(200, 120);

    QPushButton *quit = new QPushButton("Quit", widget);
    quit->setGeometry(62, 40, 75, 30);
    quit->setFont(QFont("Times", 18, QFont::Bold));

    QObject::connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
    widget->show();
    return app.exec();
}


Здесь при создании QPushButton устанавливается связь с QWidget передачей указателя на widget, в результате чего при уничтожении widget'a автоматически уничтожается quit.

QWidget и QPushButton должны уничтожаться  отдельно, как можно перед удалением объектов удалять их связь?

--

зачем такое надо: у меня идёт автоматическое удаление созданных объектов, порядок уничтожения я определить не могу. Есть только возможность самому описать функцию уничтожения объекта DESTROY(), 
по-умолчанию в DESTROY написано 
delete объект;
из-за чего при вызове DESTROY для QPushButton после DESTROY для QWidget программа завершается с "Ошибка сегментирования".

Как вариант: возможно ли вообще имея указатель на объект определить жив ли объект (NULL прописать в указатель невозможно).

PM MAIL Jabber   Вверх
JackYF
Дата 25.11.2007, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Цитата(vadiml @  25.11.2007,  20:29 Найти цитируемый пост)
возможно ли вообще имея указатель на объект определить жив ли объект

просто так - нет, уже обсуждалось в общих вопросах.

Цитата(vadiml @  25.11.2007,  20:29 Найти цитируемый пост)
у меня идёт автоматическое удаление созданных объектов

так в QT тоже, причём автоматически и без телодвижений...

Добавлено через 1 минуту и 10 секунд
Цитата(vadiml @  25.11.2007,  20:29 Найти цитируемый пост)
QPushButton *quit = new QPushButton("Quit", widget);

кстати, говоря, ты здесь можешь и не создавать "связь":

Код

QPushButton *quit = new QPushButton("Quit");

А компонент ложить на форму с помощью layout'ов.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Любитель
Дата 25.11.2007, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



Цитата(vadiml @  25.11.2007,  20:29 Найти цитируемый пост)
 у меня идёт автоматическое удаление созданных объектов, порядок уничтожения я определить не могу

На чём оно основано? Каков принцип?

В куте всё просто: есть парент, есть чайлды. Деструктор парента удаляет все чайлды. Можно явно для объекта вызвать setParent. Кстати, у тебя в итоге никто не удалиться. Нужно ызвать delete для widget или (что разумней) создать widget как стековый объект.

Добавлено через 1 минуту и 2 секунды
А вообще. setGeometry, setFixedSize - в 99% случаев есть зло. Ведь есть лэйоуты smile


--------------------
PM MAIL ICQ Skype   Вверх
vadiml
Дата 25.11.2007, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Любитель @  25.11.2007,  21:09 Найти цитируемый пост)
На чём оно основано? Каков принцип?


Для каждого созданного объекта вызывется DESTROY, это делает сборщик мусора в автоматическом режиме, видя переменную с указателем на класс.
Цитата(JackYF @  25.11.2007,  20:48 Найти цитируемый пост)
кстати, говоря, ты здесь можешь и не создавать "связь":

Цитата(JackYF @  25.11.2007,  20:48 Найти цитируемый пост)
А компонент ложить на форму с помощью layout'ов. 

Цитата(Любитель @  25.11.2007,  21:09 Найти цитируемый пост)
setGeometry, setFixedSize - в 99% случаев есть зло


Я выше написал, что это слегка подправленный пример из tutorial (Qt Tutorial 4 - Let There Be Widgets), чтоб не изобретать своего. Здесь мне надо было только показать связь между классами. С Qt я более-менее знаком.

Цитата(JackYF @  25.11.2007,  20:48 Найти цитируемый пост)
так в QT тоже, причём автоматически и без телодвижений...


В том то и дело, что мне надо или увидеть что класс уже удалён или перед удалением удалять связи чтоб это автоматически не делал Qt
PM MAIL Jabber   Вверх
bsa
Дата 25.11.2007, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



а почему не можешь всю эту "логику" удаления поместить в деструктор твоего класса?
PM   Вверх
Любитель
Дата 25.11.2007, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



Цитата(vadiml @  25.11.2007,  21:32 Найти цитируемый пост)
увидеть что класс уже удалён

Сигнал destroyed?

Цитата(vadiml @  25.11.2007,  21:32 Найти цитируемый пост)
перед удалением удалять связи

Пример:
Код

QWidget* parent = new QWidget;
QWidget* child = new QWidget(parent);

// 1
delete parent; // деструктор родителя убъет своего ребёнка

// 2
child->setParent(0); // теперь это сирота :)
delete parent;  // эти строки
delete child;     // можно поменять местами

// 3
delete child; // родитель уведомляется, что ребёнок удалён деструктором child-а
delete parent; // всё нормально

// 4
delete parent;
delete child; // а вот здесь сегфолт :)



--------------------
PM MAIL ICQ Skype   Вверх
vadiml
Дата 25.11.2007, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



вот у меня как раз 4й случай.
днём я для проверки закомментировал delete push_button и ошибки не возникло.

Вот думаю может вызвать  widget->children () и пройдя по списку QObjectList всем вызвать setParent(0); 
после чего уже и можно делать delete widget.

Добавлено через 2 минуты и 24 секунды
Цитата(bsa @  25.11.2007,  21:43 Найти цитируемый пост)
а почему не можешь всю эту "логику" удаления поместить в деструктор твоего класса? 


код могу поместить и в DESTROY, и в деструктор, главное что туда помещать
PM MAIL Jabber   Вверх
Любитель
Дата 25.11.2007, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



vadiml, ты все объекты удаляешь явно? Тогда ты прав:

Цитата(vadiml @  25.11.2007,  22:00 Найти цитируемый пост)
Вот думаю может вызвать  widget->children () и пройдя по списку QObjectList всем вызвать setParent(0); после чего уже и можно делать delete widget.




--------------------
PM MAIL ICQ Skype   Вверх
JackYF
Дата 25.11.2007, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



vadiml, ну тогда по сабжу ответ на вопрос уже дан:
Цитата(Любитель @  25.11.2007,  21:45 Найти цитируемый пост)
child->setParent(0); // теперь это сирота smile


Где хочешь, там и вызывай сию дребедень smile




--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
vadiml
Дата 25.11.2007, 23:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



подобавлял перед delete
Код

            QList<QObject *> objlist = THIS->children();
            for ( int i = 0 ; i < objlist.size() ; ++i ) {
                QObject *ch = objlist.at(i);
                ch->setParent(0);
                printf("0 to %s\n", qPrintable(ch->objectName()));
            };

тот пример, что я приводил -- сработал, а на более сложных -- всё равно вылетает.
Плюс иногда DESTROY для QApplication вызывается раньше, чем удаляются виджеты.
Да и с самим QApplication не всё чисто, например на одном примере на delete application выдало:
X Error of failed request:  RenderBadPicture (invalid Picture parameter)
  Major opcode of failed request:  152 (RENDER)
  Minor opcode of failed request:  7 (RenderFreePicture)
  Picture id in failed request: 0x2c00009
  Serial number of failed request:  1227
  Current serial number in output stream:  1248

видать хватает еще много скрытых связей, у того же QApplication на приводимом выше примере висит 4 потомка, 1 из которых тема графической оболочки.

буду думать как такое отслеживать.

PM MAIL Jabber   Вверх
Любитель
Дата 25.11.2007, 23:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



Пожалуй, проще отказаться от своего GC smile

Цитата(vadiml @  25.11.2007,  23:47 Найти цитируемый пост)
THIS

У тебя что дефан THIS -> this? А зачем,


--------------------
PM MAIL ICQ Skype   Вверх
vadiml
Дата 26.11.2007, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



это не GC, а Perl XS, 
вот синтаксис -- http://perldoc.perl.org/perlxs.html#Using-XS-With-C%2b%2b

Добавлено через 4 минуты и 41 секунду
т.е. я пищу
Код

void
QWidget::DESTROY()
    CODE:
        {
            QList<QObject *> objlist = THIS->children();
            for ( int i = 0 ; i < objlist.size() ; ++i ) {
                QObject *ch = objlist.at(i);
                ch->setParent(0);
                printf("0 to %s\n", qPrintable(ch->objectName()));
            };
            printf("del QWidget\n");
            delete THIS;
        }

на основе чего Perl XS создает с-файл с такой функцией:
Код

XS(XS_Qt__QWidget_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS(XS_Qt__QWidget_DESTROY)
{
    dXSARGS;
    if (items != 1)
        Perl_croak(aTHX_ "Usage: Qt::QWidget::DESTROY(THIS)");
    {
        QWidget *       THIS;

        if( sv_isobject(ST(0)) && (SvTYPE(SvRV(ST(0))) == SVt_PVMG) )
                THIS = (QWidget *)SvIV((SV*)SvRV( ST(0) ));
        else{
                warn( "Qt::QWidget::DESTROY() -- THIS is not a blessed SV reference" );
                XSRETURN_UNDEF;
        };
#line 1295 "QWidget.xs"
        {
            QList<QObject *> objlist = THIS->children();
            for ( int i = 0 ; i < objlist.size() ; ++i ) {
                QObject *ch = objlist.at(i);
                ch->setParent(0);
                printf("0 to %s\n", qPrintable(ch->objectName()));
            };
            printf("del QWidget\n");
            delete THIS;
        }
#line 5978 "QWidget.c"
    }
    XSRETURN_EMPTY;
}

которая потом компилируется. Все макросы определены в perl.h
PM MAIL Jabber   Вверх
Любитель
Дата 26.11.2007, 00:17 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



vadiml, я что-то не пойму, а, если вообще не объявлять этот DESTROY. Кутешные объекты очистятся автоматически. Тебе нужно что-то ещё?


--------------------
PM MAIL ICQ Skype   Вверх
archimed7592
Дата 26.11.2007, 03:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

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



Цитата(vadiml @  26.11.2007,  00:01 Найти цитируемый пост)
т.е. я пищу

Сделай то же самое, только не для QWidget, а для QObject, ибо children может быть у любого класса, наследующегося от QObject.


Цитата(Любитель @  26.11.2007,  00:17 Найти цитируемый пост)
vadiml, я что-то не пойму, а, если вообще не объявлять этот DESTROY. Кутешные объекты очистятся автоматически.

Не все и не всегда - ты же сам писал про "сирот" smile.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
vadiml
Дата 26.11.2007, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



решил пока остановиться на таком варианте:
Код

    if ( (widget->children()).size() > 0 )
         widget->deleteLater();
    else
        delete widget;


на небольших программах пока ошибок не вылазило.
Кому-нибудь с таким грабли попадались?

Добавлено через 8 минут и 43 секунды
так же думаю стоит ли запретить явное удаление QApplication, т.к. всегда DESTROY для него вызывается в перемешку с остальными, в то же время его запросто может убрать сборщик мусора если он сам не удалиться
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




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


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

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