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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Механизм parent'ов, деструкторов  (Прочитано 10714 раз)
xk
Гость
« : Октябрь 19, 2007, 16:41 »

OS: win-xp
Qt: 4.3.2

Простая до тошноты программа вываливается при закрытии окна. Причем вываливается, судя по дебаггеру где-то внутри QToolBar. Сдается мне что я чего-то не понимаю в сабжевом механизме.
Подскажите что может быть не так ? может на другой платформе/версии Qt всё нормально ?

main.cpp
Код:
#include "app.h"

int main(int argc, char **argv)
{
  CApp app(argc, argv);
  return app.run();
}

app.h
Код:
#ifndef __GRADARAPP_H__
#define __GRADARAPP_H__

#include <QApplication>
#include "guimanager.h"

class CApp : public QApplication
{
public:
  CApp(int argc, char** argv);
  ~CApp();
  int run();

private:
  CGuiManager* m_pGuiManager;
};

#endif  // __GRADARAPP_H__

app.cpp
Код:
#include "app.h"

CApp::CApp(int argc, char** argv)
: QApplication(argc, argv)
{
  m_pGuiManager = new CGuiManager(this);
}

CApp::~CApp()
{
}

int CApp::run()
{
  return exec();
}

guimanager.h
Код:
#include <QObject>
#include "mainwin.h"

class CGuiManager : public QObject
{
public:
  CGuiManager(QObject* parent);
  ~CGuiManager();

private:
  CMainWindow* m_pMainWindow;
};

guimanager.cpp
Код:
#include "guimanager.h"

CGuiManager::CGuiManager(QObject* parent)
: QObject(parent)
{
  m_pMainWindow = new CMainWindow;
}

CGuiManager::~CGuiManager()
{
  delete m_pMainWindow;
}

mainwin.h
Код:
#ifndef __MAINWIN_H__
#define __MAINWIN_H__

#include <QMenu>
#include <QAction>
#include <QToolBar>
#include <QMainWindow>

class CMainWindow : public QMainWindow
{
public:
  CMainWindow();
  ~CMainWindow();

private:
  void createActions();
  void createMenus();
  void createToolBars();
  void createStatusBar();
 
private:
  QAction*  m_pExitAct;
  QMenu*    m_pFileMenu;
  QToolBar* m_pFileToolBar;
};

#endif  // __MAINWIN_H__

mainwin.cpp
Код:
#include <QTextEdit>
#include <QMenuBar>

#include "mainwin.h"

CMainWindow::CMainWindow()
{
  createActions();
  createMenus();
  createToolBars();
 
  QTextEdit* edit = new QTextEdit(this);
  setCentralWidget(edit);
 
  show();
}

CMainWindow::~CMainWindow()
{
}

void CMainWindow::createActions()
{
  m_pExitAct = new QAction(tr("E&xit"), this);
  connect(m_pExitAct, SIGNAL(triggered()), this, SLOT(close()));
  return;
}

void CMainWindow::createMenus()
{
  m_pFileMenu = menuBar()->addMenu(tr("&File"));
  m_pFileMenu->addAction(m_pExitAct);

  return;
}

void CMainWindow::createToolBars()
{
  m_pFileToolBar = addToolBar(tr("File"));
  m_pFileToolBar->addAction(m_pExitAct);

  return;
}
Записан
Kainit
Гость
« Ответ #1 : Октябрь 19, 2007, 17:36 »

так должно писать уважающему себя мужу (если конечно не хочется ликов и ошибок)

Код:
CApp::~CApp()
{
delete m_pGuiManager;
}

Надеюсь, причина ошибки понятна...
« Последнее редактирование: Октябрь 19, 2007, 17:38 от Kainit » Записан
xk
Гость
« Ответ #2 : Октябрь 19, 2007, 17:51 »

Вот как раз не понятна  Улыбающийся
Я ведь пишу
Код:
m_pGuiManager = new CGuiManager(this);
т.е. задаю parent'а, т.е. деструктор m_pGuiManager должен автоматически вызываться в деструкторе parent'a, коим является CApp app.
Записан
EhTemka
Гость
« Ответ #3 : Октябрь 19, 2007, 18:15 »

Или я что-то недогоняю...

А как вообще у тебя происходит выход из процесса?

exec(); вижу, а где quit(), или что-то в этом роде?

Записан
Kainit
Гость
« Ответ #4 : Октябрь 19, 2007, 18:20 »

Цитировать
exec(); вижу, а где quit(), или что-то в этом роде?
Какой quit(), окститесь и поглядите самый первый пример Qt.
Код:
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QPushButton hello("Hello world!");
    hello.resize(100, 30);

    hello.show();
    return app.exec();
}
У товарища всё написано правильно.

2xk
Предлагаю поставить брекпоинты и убедиться что все деструкторы вызываются вне зависимости от того, есть ли вставка
Код:
delete m_pGuiManager
или нету.

Разумеется, у QObject с наследованием и уничтожением потомков всё в порядке.

А в чём причина неадекватного поведения? Точно сказать сложно, но причина именно в последовательности удаления и в том что в Qt по разному в двух случаях освобождает ресурсы связанные с MainWindow и с Application.

А ошибка сама по себе забавная и я вижу такую впервые, поскольку всегда за собой удалял всё сам...
« Последнее редактирование: Октябрь 19, 2007, 18:21 от Kainit » Записан
xk
Гость
« Ответ #5 : Октябрь 19, 2007, 20:31 »

В обоих случаях деструкторы вызываются в нужном порядке.. только в варианте "new CGuiManager(this)", вылетает ошибка доступа к памяти.
Попробую троллям сейчас отослать...
Записан
Kainit
Гость
« Ответ #6 : Октябрь 19, 2007, 21:35 »

Ты не понял мысли, хотя троллям ты отослать конечно можешь.

Я говорю не о порядке деструцирования твоих объектов app->pGuiManager->pMainWindow, я говорю о порядке деструцирования объектов данного приложения вообще. Если ты почитаешь исходники, или потыкаешь в проперти разных объектов (типа app, а точнее, в его список детей), то всё станет понятнее.

Когда ты явно говоришь delete pGuiManager, то сначала разрушается pGuiManager и pMainWindow, а затем уже разрушаются вспомогательные объекты, созданные QApplication  и потому всё завершается корректно.

Когда же ты не вызываешь delete pGuiManager, то дети QApplication  умирают в порядке создания, т.е., сначала всевозможные шрифтовые фабрики и т.п., а потом уже твои pGuiManager и pMainWindow (создал ты их позже и в список child-ов они попали в конец). Но по каким-то причинам, QMainWindow не знает о том что по сути весь контекст QApplication разрушился и твоя прога падает.

Цитировать
Попробую троллям сейчас отослать...
Тролли посмеются.
« Последнее редактирование: Октябрь 19, 2007, 21:42 от Kainit » Записан
Dodge
Гость
« Ответ #7 : Октябрь 20, 2007, 01:20 »

Ужос... зачем наследоватццо от QApplication? о_0

Что вам простите там понадобилось, это не Qt'шный стиль! ...и вообще... лучше избежать наследования, если это возможно. Но и не это главное... QApplication этж синглтон - ядро вашей программы, сингл тон в полном порядке и багов за ним не значитццо... тк зачем к нему своито прекручивать... жжжесть...

З.Ы. Аффтор, если не ошибаюсь, сам Страуструп( можт это был и Архангельской... ну не суть ) грозил пальчиком и говорил: ай-ай-ай... незя наследоватся без нужды... ай-ай-ай  Смеющийся
Многие опытные программисты рекомендуют применять наследование в случаех с интерфейсом... неговоря уже а множественном наследовании...

Ну это все лирика... к чему это все - ОСТАВЬ В ПОКОЕ QApplication! У него хоть диструктор и виртуальный... но лучше его не трогать. Посмотри как пишут сами троли. Загляни в экзамплы... я думаю проблемма исчезнет.
Записан
xk
Гость
« Ответ #8 : Октябрь 20, 2007, 08:45 »

Да, с наследованием от QApplication - это я погорячился Улыбающийся
Проблема решена, всем спасибо !  Улыбающийся
Записан
Cyrax
Гость
« Ответ #9 : Декабрь 19, 2007, 15:17 »

По поводу деструкторов и parent'ов:  не закрывается дочернее окно при закрытии главного.
Имеется главное окно dep и дочернее tload, оба - наследники QMainWindow.
Из главного окна создаю и отображаю дочернее окно:
Цитировать
tload = new tgLoad(this);
tload->show();
Запускаю приложение, из главного окна открываю дочернее tload. Затем закрываю главное. При этом дочернее окно не закрывается, хотя в конструкторе tload'а в качестве родителя я указываю this, т.е. объект главного окна.

Далее dDebug'ами проверяю последовательность вызова конструкторов и деструкторов.
Получаю следующие результаты:
1. Открываю dep, открываю tload, закрываю tload, закрываю dep:
Цитировать
warning: dep constructor
warning: tload constructor
warning: dep destructor
warning: tload destructor
Последние 2 сообщения выводятся только при закрытии главного окна dep. Т.е. деструктор tload вызывается не при закрытии окна tload, а только при закрытии главного окна dep.
Как по мне, должно быть так:
Цитировать
warning: dep constructor
warning: tload constructor
warning: tload destructor
warning: dep destructor
2. Открываю dep, открываю tload, закрываю dep:
Цитировать
warning: dep constructor
warning: tload constructor
warning: dep destructor
warning: tload destructor
Та же самая последовательность вызовов, при этом при закрытии главного окна дочернее не закрывается.
В данном случае должно быть так:
Цитировать
warning: dep constructor
warning: tload constructor
warning: tload destructor
warning: dep destructor

Если недопонимаю чего-то простого, просьба не РРРРРычать...
Записан
_govorilka
Гость
« Ответ #10 : Декабрь 19, 2007, 15:46 »

Сделай вот так, и попробуй запустить...
Код:
CGuiManager::~CGuiManager()
{
  //delete m_pMainWindow;
}

В твоём случае, окно должно удалиться самостоятельно (это написано внутри библиотеки).

Если хочешь удалять окна ручками, то надо писать вот так:

Код:
m_mуWindow->deleteLater();
m_mуWindow = 0;
Записан
Вячеслав
Гость
« Ответ #11 : Декабрь 19, 2007, 16:34 »

Вообще-то RTFM Подмигивающий При закрытии окно не удаляеться по-умолчанию,а скрываеться и прибиваеться парентом Подмигивающий Ставь флаг однако ....

setAttribute(Qt::WA_DeleteOnClose);
Записан
ритт
Гость
« Ответ #12 : Декабрь 19, 2007, 17:33 »

а мне вот всё-рно хочется поРРРРРычать...
неделю-две назад только закрыли эту тему, где всё развёрнуто было оговорено и расжёвано
уже 177 страниц форума - такие вопросы ну по-любому должны были проскакивать...но вот, лень же ж вам, люди, поиском-то воспользоваться?!
Записан
ритт
Гость
« Ответ #13 : Декабрь 19, 2007, 18:04 »

а амароки отнаследовались от куаппликэйшена...чёрт...как я в них разочаровался
а ведь амарок был моим любимым плеером...теперь придётся выбросить!  Грустный
Записан
Cyrax
Гость
« Ответ #14 : Декабрь 19, 2007, 19:55 »

Всё понятно, спасибо.

Цитировать
неделю-две назад только закрыли эту тему, где всё развёрнуто было оговорено и расжёвано
http://prog.org.ru/forum/index.php/topic,6541.0.html ?

Собственно, для того, чтобы при закрытии главного окна закрывались все дочерние и при этом не вываливалось ошибок, хотел вначале очистить свойство quitOnLastWindowClosed приложения (по умолчанию - установлено) + для главного окна установить свойство setAttribute(Qt::WA_DeleteOnClose, true) + законнектить "сигнал удаления главного" окна на слот quit() приложения. Поскольку у QMainWindow нет "сигнала удаления", придётся его генерировать вручную в деструкторе. Довольно муторно.
Пока остановился на варианте, когда свойство quitOnLastWindowClosed оставляю установленным + перегружаю слот closeEvent() в главном окне:
Цитировать
void dep::closeEvent(QCloseEvent *event)
{
    this->tload->close();
    QMainWindow::closeEvent(event);
}
В данном случае при закрытии главного окна вначале закрывается (hide'ится) дочернее окно (tload), затем - главное (dep). Далее срабатывает атрибут quitOnLastWindowClosed...

Поправте, если что не так.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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