Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Время жизни объекта 
:(
    Опции темы
xbarmaglot
Дата 12.9.2012, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Есть объект, который реализует всю возложенную на него логику.
Ее хотелось побить на части. Для этого я возвращаю вспомогательные объекты, которые решают узкую часть задач.
Код

class Parent : public QObject {
private:
    void func1();
    void func2();
    void func3();
    ...
    void funcN();
public :
    class Some : public QObject {
    private:
        Some(Parent* parent) : QObject(parent) {}

    public :
        void func1() { parent()->func1(); }
        void func2() { parent()->func2(); }
    }

    Some* get_some() { return new Some(this); }
}


Ну или объект Some имеет открытый конструктор и используется так.
Код

Parent parent;
Some some(&parent);


Если бы Some не использовался снаружи, то имел бы время жизни не более чем время жизни Parent.
Тогда при удалении Parent разрушен был бы и Some.

Но что будет если
Код

Parent* parent = new Parent();
Some* some = parent->get_some();
delete parent;
some->func1();


Будет ли хотябы отладочное разумное сообщение или просто вылет приложения?
Не отдавать же классу Some в конструкторе QSharedPointer на Parent. Ведь в документации обычно не пишут про время
жизни вспомогательных объектов. По крайнем мере я в документации QT это не встречал. 

PM MAIL   Вверх
Amp
Дата 12.9.2012, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вылет. В документации они дают вполне разумные рекомендации "We do not recommend holding pointers to child objects from outside the parent". Можно также подписаться на сигнал destroyed().

Это сообщение отредактировал(а) Amp - 12.9.2012, 13:04
PM MAIL   Вверх
xbarmaglot
Дата 12.9.2012, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Amp @  12.9.2012,  13:04 Найти цитируемый пост)
Вылет. В документации они дают вполне разумные рекомендации "We do not recommend holding pointers to child objects from outside the parent". 

ну а как тогда, например, QTextStream и QFile. Я могу так же грохнуть QFile раньше.

Цитата(Amp @  12.9.2012,  13:04 Найти цитируемый пост)
Можно также подписаться на сигнал destroyed().

А что делать с объектом, который его получил? Сам себя то он не грохнет....

PM MAIL   Вверх
borisbn
Дата 12.9.2012, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



Цитата(xbarmaglot @  12.9.2012,  13:07 Найти цитируемый пост)
 Сам себя то он не грохнет...

почему ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
xbarmaglot
Дата 12.9.2012, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(borisbn @  12.9.2012,  13:11 Найти цитируемый пост)
почему ? 

так я его держу

Код

QFile* file = new QFile();
QTextStream stream(file);
delete file;
stream <- здесь даже если stream получил сигнал, его можно использовать

PM MAIL   Вверх
Amp
Дата 12.9.2012, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(xbarmaglot @  12.9.2012,  13:07 Найти цитируемый пост)
ну а как тогда, например, QTextStream и QFile. Я могу так же грохнуть QFile раньше.

Обычно QFile создается либо на стэке, либо является приватным членом класса. При таких раскладах его сложно случайно испортить или удалить. Но вообще надо следить и стараться выстраивать логику приложения, чтобы максимально обезопасить себя от таких ситуаций. И вне Qt можно с легкостью остаться с невалидным указателем на руках.

Цитата(xbarmaglot @  12.9.2012,  13:07 Найти цитируемый пост)
А что делать с объектом, который его получил? Сам себя то он не грохнет....

Сигнал получает тот объект, к которому он присоединен. Если речь о том объекте, который послал сигнал - то он после сигнала будет уничтожен. Это уведомление.
PM MAIL   Вверх
math64
Дата 12.9.2012, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 23
Всего: 72



Организуйте класс так:
Код

class Some {
class Private : public QObject { Some* parent; ... };
Private* p;
public:
Some();
Some(const Some&);
~Some();
void someFunc() { if (p != NULL) p->someFunc(); }
};

При удалении связанного объекта, Some::Private получит сигнал, прочистит поле p в родительском Some и удалится.
Some при вызове методов проверяет поле p на NULL- напрямую к методам Some::Private обратиться нельзя.
PM   Вверх
xbarmaglot
Дата 12.9.2012, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



math64, я как раз от этого хотел и уйти.
У меня объект имеет доступ с несколький десяткам интерфейсов (нак исторически сложилось smile)
Я хотел не вызывать их в одном класе
Код

class Owner 
{
    bool Interface1_Method1();
    bool Interface1_Method2();
    ...
    bool InterfaceN_MethodN();
}


А поделить их с помощью классов оберток. Тогда можно было бы раздавать их по необходимости.
А не всю кучу, чтоб кто-нибудь случайно что-то не дернул smile
PM MAIL   Вверх
math64
Дата 12.9.2012, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 23
Всего: 72



А кто мешает добавить в мой код ещё оберток - сколько тебе нужно.
Идея - сам объект сидит во внутреннем private классе, его даже не обязательно объявлять в заколовке и раскрывать пользователю твоего API его структуру. А обётрок на него можешь наплодить сколько хочешь.
Код

class Some {
public:
class Wrapper1;
private:
class Private : public QObject {
  friend class Wrapper1; // Вероятно потребуется объявить другом, родительский класс и вложенный - друзья в автомате
  int counter;
  ~Private();
public:
  void unlink()  {
    if (--counter == 0)
    delete this; // удалена последняя ссылка - удаляем объект 
  }
};
Private* p;
public:
Some();
Some(const Some&);
Some& operator=(const Some&);
~Some();
void someFunc() { if (p != NULL) p->someFunc(); }
class Wrapper1 {
   Private* p;
   Wrapper1(Private* p);
   Wrapper1(const Wrapper1&);

public:
   Wrapper1(const Wrapper1&);
   Wrapper1& operator=(const Wrapper1&);
   void someFunc1() {
     if (p != NULL)
        p->someFunc1();
  }
};
Wrapper1 getWrapper1() { return Wrapper1(p);
};

При этом нужно не забывать определить копирующий конструктор и оператор присваивания и увеличивать там счётчик.
Для работы со счётчиком в Qt есть специальный класс,  с ...Atomic... в названии
PM   Вверх
xbarmaglot
Дата 12.9.2012, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



math64, а чем твой код отличается от моего ?
PM MAIL   Вверх
math64
Дата 12.9.2012, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 23
Всего: 72



Ты же не даёшь свой полный код - поэтому не могу точно дать ответ.
Принцип такой: не давать пользователю доступ непосредственно к объекту, а только через различные обертки.
Даже при создании объекта пользователь получает только его обертку.
Как это реализовать - без разницы.
Тогда ты всегда будешь знать сколько ссылок на объект осталось и когда его можно удалить.

Не упомянуто осталось, что если у тебя есть объекты A и В, связанные друг с другом, то удалять их можно только когда счетчики внешних ссылок на оба из них обнулятся или связь между ними разорвётся.
PM   Вверх
xbarmaglot
Дата 12.9.2012, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(math64 @  12.9.2012,  15:11 Найти цитируемый пост)
Ты же не даёшь свой полный код - поэтому не могу точно дать ответ.
Принцип такой: не давать пользователю доступ непосредственно к объекту, а только через различные обертки.
Даже при создании объекта пользователь получает только его обертку.
Как это реализовать - без разницы.

ну я, впринципе, привел пример, который хотел реализовать.

Идея в том, что ели парент возвращает созданный объект через указатель, то он его подписывает на себя.
Если пользователь забыл его грохнуть, то он грохнется через связь QObject.

Если сделать класс свободным, то за время жизни отвечает сам создатель класса.

Добавлено через 4 минуты и 32 секунды
Остался лишь вопрос - если парент вернет указатель и потом парент грохнут.
Он попытается грохнуть созданный им объект, который у меня. Что тогда будет ?

Добавлено через 5 минут и 48 секунд
В отладке ругается на битую кучу. Получается, что связь по QObject можно делать только для закрытых дочерних классов ?
PM MAIL   Вверх
math64
Дата 12.9.2012, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 23
Всего: 72



Так я тебе говорю: твой Parent должен стать приватным классом. Удалить его сможешь только ТЫ (на крайняк объяви приватными конструктор, деструктор и операторы копирования). Доступ к нему пользователем - только через обёртки. Класс удаляется ТОБОЙ когда все обертки будут удалены. Чтобы это проконтролировать - достаточно иметь счётчик числа обёрток. У оберток обязательны конструктор копирования, оператор присваивания и деструктор, в которых будет изменяться счётчик.

ЗЫ: Класс наследуемый от QObject должен быть объявлен в заголовке, по которому moc создаёт файл moc_XXXX.cpp Иначе при линковке будут неопределённые символы. Не забудь про макрос Q_OBJECT.
PM   Вверх
xbarmaglot
Дата 12.9.2012, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(math64 @  12.9.2012,  15:44 Найти цитируемый пост)
Так я тебе говорю: твой Parent должен стать приватным классом. Удалить его сможешь только ТЫ (на крайняк объяви приватными конструктор, деструктор и операторы копирования). 

аааа.... понятно о чем ты говорил


Цитата(math64 @  12.9.2012,  15:44 Найти цитируемый пост)
Класс удаляется ТОБОЙ когда все обертки будут удалены. Чтобы это проконтролировать - достаточно иметь счётчик числа обёрток. У оберток обязательны конструктор копирования, оператор присваивания и деструктор, в которых будет изменяться счётчик.

ну удалять его не обязательно. Хотелось бы
1. либо запретить его удалять пока есть обертки
2. либо в отладке выводить разумное сообщение (а не крах кучи smile)

Похоже мне сможет помочь лишь boost::shared_ptr и boost::shared_from_this
Но я думал, что раз парент в QT может грохать потомков, то защита от такого случая тоже какая-то есть.
PM MAIL   Вверх
xbarmaglot
Дата 12.9.2012, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



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

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

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


 




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


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

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