Russian Qt Forum

Qt => Общие вопросы => Тема начата: demaker от Январь 22, 2014, 15:35



Название: setModel
Отправлено: demaker от Январь 22, 2014, 15:35
Код
C++ (Qt)
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{        
   ui->setupUi(this);
 
    root = new QObject(this);
 
   treeview = new TreeView(this);
   treemodel = new TreeModelBrowser(root);
   treeview->setModel(treemodel);
 
}
 

Скажите в данной ситуации treeview является  дочкой MainWindow или treemodel?


Название: Re: setModel
Отправлено: Alex Custov от Январь 22, 2014, 15:51
Если имеется ввиду всё-таки модель, то документация:

Цитировать
void QAbstractItemView::setModel(QAbstractItemModel *model)
...
The view does not take ownership of the model unless it is the model's parent object because the model may be shared between many different views.

Если view, то непонятно почему возник такой вопрос - это первые уроки по Qt. Объект является ребёнком того объекта, который был передан как родитель в конструкторе. Т.е. MainWindow.


Название: Re: setModel
Отправлено: demaker от Январь 22, 2014, 16:01
Согласен
Но когда я закрываю главное окно MainWidow в дебаг не выводится "Delete TreeView"

Код
C++ (Qt)
void TreeView::actWscan()
{
           wps = new widgetScan()            
           wps->show();  
}
 
 
TreeView::~TreeView()
{
   qDebug()<<"Delete TreeView";
 
   if(wscan != NULL)
   {
       wscan->close();
       wscan = NULL;
   }
}
 

Код
C++ (Qt)
widgetScan::widgetScan(QWidget *parent):
   QWidget(parent)
{
   setAttribute(Qt::WA_DeleteOnClose);
}
 


Название: Re: setModel
Отправлено: Hrundel от Январь 23, 2014, 00:38
А ты удаление объекта явно вызови и увидишь.

На сколько я понимаю, при удалении наследников, просто, адрес памяти удаляется из таблицы, а бинарный мусор на этом месте остается не перезаписанным нулями (то есть не равно 0х0, это хорошо видно при дебаге). Однако это место в памяти уже не является резервированным.

Следовательно, если хочешь чтобы происходили события для деструктора - вызывай его явно.

В твоем варианте wps = new widgetScan() не является потомком TreeView, а значит его нужно удалять. Поэтому в событии close() нужно вызвать деструктор TreeView.

Если написать  wps = new widgetScan(this),  то будет удаляться и без деструктора по цепочке от дальнего предка к родителю.


Название: Re: setModel
Отправлено: Alex Custov от Январь 23, 2014, 10:42
Следовательно, если хочешь чтобы происходили события для деструктора - вызывай его явно.

Это бред, странно что приходится обсуждать вызов деструктора тут  :o


Название: Re: setModel
Отправлено: Serr500 от Январь 23, 2014, 11:47
На сколько я понимаю, при удалении наследников, просто, адрес памяти удаляется из таблицы, а бинарный мусор на этом месте остается не перезаписанным нулями (то есть не равно 0х0, это хорошо видно при дебаге). Однако это место в памяти уже не является резервированным.

Следовательно, если хочешь чтобы происходили события для деструктора - вызывай его явно.
Абсолютно неверно! При удалении обекта всегда вызывается его деструктор (экстремальные случаи рассматривать не будем  ;) ). То есть стековые переменные при выходе из области видимости автоматически разрушаются с вызовом деструктора, а переменные в куче разрушаются с вызовом деструктора при удалении оператором delete.

А если Вам приходится вызывать деструктор явно, то у Вас почти наверняка ошибка в коде. Явный вызов деструктора приемлем, пожалуй, только при написании собственного распределителя памяти.

Правы Вы только в одном - обычно при разрушении объектов их память не обнуляется.


Название: Re: setModel
Отправлено: Hrundel от Январь 23, 2014, 12:41
Простите за некорректную формулировку на русском, я информатику на немецком изучаю. Вообще, под явным вызовом деструктора я подразумевал применение оператора delete. "Умные указатели" я, честно говоря, слабо понимаю, потому что на лекциях их затронули очень поверхностно. (Но речь то надо толкнуть, чтобы проверить что другие скажут :D )


Название: Re: setModel
Отправлено: Serr500 от Январь 24, 2014, 09:22
"Умные указатели" я, честно говоря, слабо понимаю, потому что на лекциях их затронули очень поверхностно.
Там и понимать-то нечего.  :) Если рассматривать самый простой "умный указатель", то это некий объект с конструктором и деструктором, который содержит ссылку на некие общие данные. Общие данные состоят из обычного указателя на нужный нам объект и счётчика ссылок. При создании копии умного указателя счётчик ссылок увеличивается, при разрушении - уменьшается. Последний разрушаемый умный указатель разрушает объект, указатель на который он хранит. Вот и всё.


Название: Re: setModel
Отправлено: demaker от Январь 24, 2014, 13:56
Код
C++ (Qt)
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   newWidow = NULL;
   connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(addNewWindow()));
 
   setAttribute(Qt::WA_DeleteOnClose);
}
 
MainWindow::~MainWindow()
{
   delete ui;
 
   if(newWidow != NULL)
   {
       newWidow->close();
       delete newWidow;
       newWidow = NULL;
   }
}
 
void MainWindow::addNewWindow()
{
   if(newWidow == NULL)
   {
       newWidow = new MyWidget;
       connect(newWidow,SIGNAL(closeMyWidget()),this,SLOT(nullNewWindow()));
       newWidow->show();
   }
}
 
void MainWindow::nullNewWindow()
{
   newWidow = NULL;
}
 
 

Код
C++ (Qt)
MyWidget::MyWidget(QWidget *parent):
   QWidget(parent)
{
   setAttribute(Qt::WA_DeleteOnClose);
}
 
MyWidget::~MyWidget()
{
   Q_EMIT closeMyWidget();
}
 

Не могу понять почему код работает с ошибкой ???
Пожалуйста подскажите :)


Название: Re: setModel
Отправлено: kambala от Январь 24, 2014, 14:19
delete newWidow; — убери, оно и так само удаляется


Название: Re: setModel
Отправлено: demaker от Январь 24, 2014, 14:35
delete newWidow; — убери, оно и так само удаляется

убрал ,но
в debug пишет
Код:
Okna-build-desktop\debug\Okna.exe завершился с кодом -1073741819


Название: Re: setModel
Отправлено: lit-uriy от Январь 24, 2014, 14:48
demaker, если у тебя функция main выглядит так:
Код
C++ (Qt)
Qapplication app;
MainWindow w;
w.show();
return app.exec();
то ты никогда не дождёшся работы деструктора, т.к. деструктор w должен вызваться после того как закончит работу app.exec(), но программа тут же завершается.

Для тестов можешь попробовать это (http://www.forum.crossplatform.ru/index.php?showtopic=9735&view=findpost&p=65870)


Название: Re: setModel
Отправлено: kambala от Январь 24, 2014, 14:49
запускаешь через дебаггер и смотришь где падает. ты будто впервые в жизни ловишь баги. хотя, судя по твоим темам, ты будто все делаешь впервые.

P.S. вместо NULL пиши 0.


Название: Re: setModel
Отправлено: demaker от Январь 24, 2014, 15:04
Для тестов можешь попробовать это (http://www.forum.crossplatform.ru/index.php?showtopic=9735&view=findpost&p=65870)

Спасибо, но не помогло


Название: Re: setModel
Отправлено: demaker от Январь 24, 2014, 15:11
запускаешь через дебаггер и смотришь где падает. ты будто впервые в жизни ловишь баги. хотя, судя по твоим темам, ты будто все делаешь впервые.

И что мне с этим делать ???


Название: Re: setModel
Отправлено: gil9red от Январь 24, 2014, 15:17
через вывод в консоль можно локализовать место, где падает :)
Код
C++ (Qt)
qDebug() << 1;
foo * a;
qDebug() << 2;
a->doIt();
qDebug() << 3;
 
консоль:
1
2
Программа неожиданно завершилась бла-бла-бла...
 
Значит, ошибка между 2 и 3 :)


Название: Re: setModel
Отправлено: kambala от Январь 24, 2014, 15:47
ты ведь нам свою функцию main не показал. если ты там создаешь mainwindow на стеке, то при закрытии главного окна программа пытается удалить память второй раз (атрибут удаления в mainwindow). удали этот атрибут и ошибка пропадет.


Название: Re: setModel
Отправлено: Hrundel от Январь 24, 2014, 19:04
Слушай, kambala, вопрос к теме, но немного в сторону.
*(Кстати спасибо за объяснение "умных указателей" - стало чуть понятней)
Был у нас такой предмет на втором семестре - Теоретическая информатика, из которой очень хорошо можно было понять как резервируется физическая память, как ALU работает с регистрами и прочее. Но !!! Вот на программировании, что I что II никто не удосужился объяснить какие процессы происходят в памяти программ с точки зрения высоких языков (С/СPP). Подскажи литературу к этому вопросу. Спасибо!


Название: Re: setModel
Отправлено: kambala от Январь 24, 2014, 19:44
не совсем понял вопрос. какой код напишешь — то и будет происходить. высокоуровневый код же преобразовывается в низкоуровневый (инструкции процессора). тебя интересует как команды С/С++ превращаются в ассемблерный код?


Название: Re: setModel
Отправлено: Hrundel от Январь 24, 2014, 19:54
Почти. Просто, так же как и у автора поста порой возникают серьезные проблемы с пониманием того, как обращаться с памятью.
Например: создаю я указатель на диалоговое окно, которое посылает сигнал. После того как сигнал обработан я удаляю его оператором delete. Всегда спрашиваю себя, что там происходит в памяти? Как быть уверенным, что память полностью очистилась. А close() идентичен опературу delete или нет?

Или как в случае приведенном выше

если создаешь mainwindow на стеке, то при закрытии главного окна программа пытается удалить память второй раз (атрибут удаления в mainwindow). удали этот атрибут и ошибка пропадет.

Надеюсь сумел донести смысл того, что мне не понятно.


Название: Re: setModel
Отправлено: Hrundel от Январь 24, 2014, 19:57
Хочется иметь в голове стройное представление как и что там в памяти происходит. Особенно  с указателями.


Название: Re: setModel
Отправлено: kambala от Январь 24, 2014, 21:08
После того как сигнал обработан я удаляю его оператором delete. Всегда спрашиваю себя, что там происходит в памяти? Как быть уверенным, что память полностью очистилась.
о таких тонкостях как-то никогда не задумывался :) как я это понимаю: область «кучи», на которую указывает указатель, помечается удаленной и становится невалидной. далее ОС уже решает что делать с этим куском памяти (изъять ее у программы или нет). может кто-то поправит/дополнит мой ответ.

очистилась эта память или нет ты не узнаешь, но вот то, что вероятнее всего программа упадет при обращении в эту область памяти (например попытка вызвать метод у удаленного указателя) — это да.

стек же — это фиксированная область памяти (уже выделенная), в которой переменные просто занимают место (не нужно у ОС явно запрашивать память как в случае с кучей). попал на стек — ты уже с памятью, вылетел со стека — и ты «без памяти» (удаление происходит автоматически), т.е. переменная находится в невалидной области памяти. послеэ этого обратиться к переменной не даст компилятор (она будет вне области видимости), но при попытке удалить такую переменную delete'ом, она будет еще раз удалена при вылете со стека, что и приведет к падению программы.
А close() идентичен опературу delete или нет?
нет конечно. но если ты окну поставишь атрибут WA_DeleteOnClose, то оно заодно и удалится.
Цитировать
bool QWidget::close() [slot]
Closes this widget. Returns true if the widget was closed; otherwise returns false.

First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.


Название: Re: setModel
Отправлено: Hrundel от Январь 24, 2014, 22:03
Вот, спасибо, теперь понятно стало. А то я все путал. Для меня и steck и куча были одним и тем же! Прояснилось!


Название: Re: setModel
Отправлено: kambala от Январь 24, 2014, 23:07
stack ;)


Название: Re: setModel
Отправлено: Figaro от Январь 25, 2014, 07:25
ТС да прочитайте про ассемблер книги под Вашу конкретную платформу... практически любой сишный или плюсовый компилятор умеет выдавать листинг ассемблера


Название: Re: setModel
Отправлено: demaker от Январь 27, 2014, 09:24
Спасибо ,kambala, за разъяснения :)