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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QScopedPointer forward declaration  (Прочитано 5939 раз)
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« : Май 26, 2011, 20:42 »

Такой код:

myclass.h:
Код
C++ (Qt)
#ifndef MYCLASS_H
#define MYCLASS_H
 
#include <QScopedPointer>
 
class MyClass2;
 
class MyClass
{
public:
 MyClass();
 ~MyClass();
 QScopedPointer<MyClass2> _ptr;
 
};
 
#endif // MYCLASS_H
 

myclass.cpp:
Код
C++ (Qt)
#include "myclass.h"
#include "myclass2.h"
 
MyClass::MyClass()
{
this->_ptr.reset(new MyClass2);
}
 
MyClass::~MyClass() { }
 

myclass2.h:
Код
C++ (Qt)
#ifndef MYCLASS2_H
#define MYCLASS2_H
 
#include "myclass.h"
 
class MyClass2
{
public:
 MyClass2() { };
 ~MyClass2() { };
};
 
#endif // MYCLASS2_H
 

main.cpp:
Код
C++ (Qt)
#include "myclass.h"
 
int main(int argc, char *argv[])
{
MyClass obj;
}
 

Вопрос в том, зачем для MyClass'а, в котором мембером является QScopedPointer, при операции forward declaration необходимо обязательно объявлять деструктор, может кто-то выяснил это? Без деструктора бооольшой ерор. Думал может по умолчанию деструктор идёт как virtual (в доке по QScopedPointer такой какбэ запрещается), но если с ним, то всё ок. Не люблю такой подход - объявлять их пустыми, класс MyClass ведь никем не наследуется чтоб объявлять и виртуалить энтот деструктор...
« Последнее редактирование: Май 26, 2011, 20:53 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
asvil
Гость
« Ответ #1 : Май 26, 2011, 20:57 »

А еще для определения функции, которая будет выполняться параллельно функции main необходимо писать целый класс. Наверно просто смиритесь.
Записан
Akon
Гость
« Ответ #2 : Май 26, 2011, 22:28 »

Потому что в этом случае тип для скопед-поинтера (MyClass2) будет полностью определенным (в деструкторе скопед-поинтера находится что-то типа checked_delete).

Просто подумай, как компилятор будет генерировать код и какая информация будет доступна в точках генерации деструкторов.
Записан
zenden
Гость
« Ответ #3 : Май 26, 2011, 22:32 »

Пусть лучше требует деструктор, чем ведёт себя как std::auto_ptr на некоторых компиляторах, который в таких случаях память освобождает, но деструктор не вызывает.
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #4 : Май 26, 2011, 22:36 »

Пусть лучше требует деструктор, чем ведёт себя как std::auto_ptr на некоторых компиляторах, который в таких случаях память освобождает, но деструктор не вызывает.
жестоко)
Записан

kubuntu/Win7/x64/NetBeans
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #5 : Май 26, 2011, 22:47 »

Потому что в этом случае тип для скопед-поинтера (MyClass2) будет полностью определенным (в деструкторе скопед-поинтера находится что-то типа checked_delete).

Просто подумай, как компилятор будет генерировать код и какая информация будет доступна в точках генерации деструкторов.

Код структуры, которая чистит объект qscopedpointer'a:
Код
C++ (Qt)
template <typename T>
struct QScopedPointerDeleter
{
   static inline void cleanup(T *pointer)
   {
       // Enforce a complete type.
       // If you get a compile error here, read the secion on forward declared
       // classes in the QScopedPointer documentation.
       typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
       (void) sizeof(IsIncompleteType);
 
       delete pointer;
   }
};
 

Требует завершённый тип, даже в доку посылает, с этим понятно.
Но причём тут описание пустого деструктора парента-то? Чем конкретно это помогает? Интересен сам подход.
Получается, что если описано тело пустого деструктора класса, мембером которого является qscopedpointer, который, в свою очередь завязан с объектом при forward declaration, то этот qscopedpointer начинает понимать тип объекта, на который ссылается, как завершённый. Мистика.
« Последнее редактирование: Май 27, 2011, 00:24 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Май 27, 2011, 00:42 »

Но причём тут описание пустого деструктора парента-то? Чем конкретно это помогает? Интересен сам подход.
Получается, что если описано тело пустого деструктора класса, мембером которого является qscopedpointer, который, в свою очередь завязан с объектом при forward declaration, то этот qscopedpointer начинает понимать тип объекта, на который ссылается, как завершённый. Мистика.
Если деструктор MyClass объявлен, то удаление "инстанциируется" в этом деструкторе - а там MyClass2 уже известен. А если нет, то код деструктора по умолчанию должен быть создан в main - но здесь не получается т.к. scoped не знает тип удаления.

Вообще расходы на изучение таких мелких классов часто превышают их usability Улыбающийся Еще один момент - затрудняется отладка - пока до тела доберешься...
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #7 : Май 27, 2011, 01:03 »

Если деструктор MyClass объявлен, то удаление "инстанциируется" в этом деструкторе - а там MyClass2 уже известен.
Что значит "инстанциируется" в деструкторе, т.е. в чём разница, деструктор по умолчанию это или объявленный мной? В обоих же случаях будет вызван деструктор QScopedPointer'а... Получается, что если деструктор по умолчанию, то тип, используемый в QScopedPointer'е - неизвестен (интересно почему).

Вообще расходы на изучение таких мелких классов часто превышают их usability Улыбающийся Еще один момент - затрудняется отладка - пока до тела доберешься...
так ведь дело не в изучении классов, а в понимании данного подхода.
« Последнее редактирование: Май 27, 2011, 01:25 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Май 27, 2011, 02:12 »

Что значит "инстанциируется" в деструкторе, т.е. в чём разница, деструктор по умолчанию это или объявленный мной? В обоих же случаях будет вызван деструктор QScopedPointer'а... Получается, что если деструктор по умолчанию, то тип, используемый в QScopedPointer'е - неизвестен (интересно почему).
Компилятор создает код когда увидит что темплейт используется (т.е. заряжено конкретным типом). Это происходит в конкретной единице трансляции (cpp файле) и к этому моменту все подробности должны быть компилятору известны. Вы объявили деструктор MyClass, значит что в main он вызовется - а что он там дальше будет делать - за это ответит код созданный в том cpp где деструктор. Напр. просто перенесите тело ~MyClass::MyClass() в main.cpp - и компилятор опять не пропустит.

так ведь дело не в изучении классов, а в понимании данного подхода.
Да нет там никакого особого/великого подхода  Улыбающийся Просто необходимость удаляться при выходе их ф-ции/контекста возникает часто - вот и придумали утилитарный класс. Им можно пользоваться или нет - варианты примерно равноценны.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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