Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Smart pointer и meta-properties 
V
    Опции темы
xRaux
Дата 16.2.2012, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Задача следующая. Нужно реализовать класс, который будет выступать в роли умного указателя: операторы * и -> отложенно создают объект, который инициализируется значениями из базы данных. Проблема в том, что этот класс должен использоваться вместе с мета-свойствами Qt, которые не позволяют полноценно работать с шаблонами. У меня родился такой вариант:

Код

class MappedObject : public QObject
{
public:
    void load();
};

class MappedObjectPtrBase
{
public:
    virtual MappedObject* operator*() { return 0; }
};

Q_DECLARE_METATYPE(MappedObjectPtrBase*)

template<typename T>
class MappedObjectPtr
{
public:
    MappedObject* operator*()
    {
        if (!pMappedObject)
        {
            pMappedObject = new T();
            pMappedObject->load();
        }
        return pMappedObject;
    }
    
private:
    T* pMappedObject;
};

class SomeMappedObject : public MappedObject
{
    Q_OBJECT
    Q_PROPERTY(MappedObjectPtrBase* someProp READ getSomeProp WRITE setSomeProp)
public:
    MappedObjectPtrBase* getSomeProp()const { return somePropValue; }
    void setSomeProp(MappedObjectPtrBase* p) { somePropValue = p; }
    
protected:
    MappedObjectPtrBase* somePropValue;
};


Но он меня сильно не устраивает.
1. SomeMappedObject (как и любой другой потомок MappedObject) вынужден использовать голые указатели со всеми вытекающими - создавать объект в конструкторе, удалять в деструкторе.
2. Нет контроля типов для someProp. Хотелось бы писать что-то вроде Q_PROPERTY(MappedObjectPtr<SomeMappedObject> propName ...)
Короче говоря, запутался я совсем. Может быть, возможно реализовать какой-нибудь другой, более приемлемый вариант? Заранее спасибо.
PM MAIL   Вверх
bsa
Дата 17.2.2012, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



xRaux, а зачем тебе это нужно?
PM   Вверх
xRaux
Дата 17.2.2012, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Что именно, сорри?
PM MAIL   Вверх
bsa
Дата 17.2.2012, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(xRaux @  17.2.2012,  11:37 Найти цитируемый пост)
Что именно, сорри? 

Цитата(xRaux @  16.2.2012,  21:15 Найти цитируемый пост)
Нужно реализовать класс, который будет выступать в роли умного указателя: операторы * и -> отложенно создают объект, который инициализируется значениями из базы данных.


Зачем тебе нужен такой класс? Просто есть подозрение, что ты пытаешься решить основную задачу не теми методами. Поэтому залез в такие дебри. Если ты озвучишь основную задачу, то тебе подскажут оптимальное решение.

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


Новичок



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

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



Это нечто вроде ORM - данные из базы мэппируются на объекты через свойства. Проблема в поддержке foreign keys - при мэппинге из такой, например, таблицы:
Код

CREATE TABLE book(id INTEGER PRIMARY KEY, title TEXT, author_id INTEGER, FOREIGN KEY(author_id) REFERENCES author(id));
CREATE TABLE author(id INTEGER PRIMARY KEY, name TEXT);

на класс
Код

class Book : public MappedObject
{
public:
    QString title;
    Author* author;
};

у меня возникают проблемы с полем author. Как его мэппировать? Хотелось бы, чтоб объект Author инициализировался не сразу при инициализации Book, а только при необходимости, то есть обращении к нему. Вот у меня и появилась мысль о том, что нужно сделать умный указатель.

Это сообщение отредактировал(а) xRaux - 17.2.2012, 11:30
PM MAIL   Вверх
borisbn
Дата 17.2.2012, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(xRaux @  17.2.2012,  11:28 Найти цитируемый пост)
Проблема в поддержке foreign keys - при мэппинге из такой, например, таблицы

дык делай SELECT с LEFT JOIN'ом. нет ?


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


Новичок



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

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



Цитата(borisbn @  17.2.2012,  12:35 Найти цитируемый пост)
дык делай SELECT с LEFT JOIN'ом. нет ?

База данных может иметь довольно сложную структуру +связи один ко многим. Имхо без отложенной выборки здесь все равно не обойтись. Или я что-то не понимаю?
PM MAIL   Вверх
bsa
Дата 17.2.2012, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



xRaux, помести все свойства класса в приватную область. А доступ к ним через методы (как собственно в Qt сделано). При вызове метода свойства будут при необходимости инициализироваться и отдаваться пользователю.
PM   Вверх
xRaux
Дата 17.2.2012, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



bsa, то есть примерно так?
Код

class Book : public MappedObject
{
    Q_PROPERTY(Author* author READ getAuthor WRITE setAuthor)
    
    std::shared_ptr<Author> valueAuthor;
public:
    Author* getAuthor()const
    {
        if (!valueAuthor)
        {
            valueAuthor.reset(new ValueAuthor());
            valueAuthor->load();
        }
        return valueAuthor.get();
    }
};

Нужно еще где-то хранить информацию об объекте Author, который должен быть создан (в этом примере - author_id). Это можно реализовать в защищенном интерфейсе MappedObject. Но опять же мне не нравится, что свойство отдает неизвестно кому голый указатель. Смириться?
PM MAIL   Вверх
mes
Дата 17.2.2012, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



xRaux, не могу до конца вашу затею понять.. 
для чего наследование от MappedObject ? 


--------------------
PM MAIL WWW   Вверх
xRaux
Дата 17.2.2012, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(mes @  17.2.2012,  15:34 Найти цитируемый пост)
для чего наследование от MappedObject ? 

Можно аналогичный механизм реализовать и без наследования, суть не в этом. Просто так удобнее - можно предоставить методы типа load/save/create для синхронизации с базой данных. Практически аналогичный кодес есть, например, в QDjango. Правда, она для моих целей не совсем подходит, да и не нужна мне полноценная ORM. Плюс, реализованный там подход к сабжу, насколько я понял - те же голые указатели с ручной аллокацией-деаллокацией. Я хотел чуть-чуть это усовершенствовать.

Это сообщение отредактировал(а) xRaux - 17.2.2012, 15:53
PM MAIL   Вверх
bsa
Дата 17.2.2012, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код
class Book : public MappedObject
{
public:
    Book() : author_(0) {}
    ~Book() {
        delete author_;
    }
    Author& author() {
        if (!author_) {
            author_= new Author;
            author_->load(); //а в конструктор никак нельзя это поместить?
        }
        return *author_;
    }
private:
    Author *author_;
};


Это сообщение отредактировал(а) bsa - 17.2.2012, 16:24
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


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

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




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


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

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