Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > Пара вопросов по Q_PROPERTY


Автор: yngwie19 10.6.2009, 23:37
Здравствуйте. Разбираю пример из книги по Qt. Пример по использованию макроса QPROPERTY. Вот он
Код

class MyClass : QObject
{
    Q_OBJECT
    Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)

    private:
        bool m_bReadOnly;
    public:
        MyClass(QObject *proj = 0) : QObject(proj), m_bReadOnly(false)
        {;
        }
        void setReadOnly(bool bReadOnly)
        {
            m_bReadOnly = bReadOnly;
        }
        bool isReadOnly()const
        {
            return m_bReadOnly;
        }
    
};

Мне не очень понятна вот эта строчка
Код

MyClass(QObject *proj = 0) : QObject(proj), m_bReadOnly(false)

инициализация объекта базового класса QObject делается объектом этого же класса, который инициализирован в конструкторе MyClass(), Но ведь конструктор MyClass вызывается после конструктора QObject, как так?

Автор: SABROG 11.6.2009, 11:34
Цитата(yngwie19 @  10.6.2009,  23:37 Найти цитируемый пост)
MyClass(QObject *proj = 0) : QObject(proj), m_bReadOnly(false)


Это уже к создателям C++. Как мне кажется (рыться в стандарте не хочеться) происходит всё по следующей схеме:

* ты вызываешь конструктор класса MyClass и передаешь в него указатель
* вызываются базовые конструкторы
* конструктор MyClass продолжает своё выполнение и инициализацию членов

Автор: yngwie19 11.6.2009, 11:44
SABROG, ну понятно, т.е вызов конструктора должен быть таким?
Код

int main(int argc, char** argv)
{  
      Object *object = new Object;
      MyClass *my = new MyClass(object);
      
      return 0;
}

Автор: ecspertiza 11.6.2009, 11:45
Тут на самом деле ничего сложного, эта конструкция заменит примерно следующую

Код

class MyClass : QObject
{
    Q_OBJECT
    Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
    private:
        bool m_bReadOnly;
    public: 
         MyClass(QObject *proj = 0);
};

        MyClass::MyClass(QObject *proj) 
                     : QObject(proj), m_bReadOnly(false)
        {
        
        }
        
        void setReadOnly(bool bReadOnly)
        {
            m_bReadOnly = bReadOnly;
        }
       
        bool isReadOnly()const
        {
            return m_bReadOnly;
        }
   


Код

MyClass(QObject *proj = 0) : QObject(proj), m_bReadOnly(false)


Примет параметр proj который ты передашь при создании класса, и скажет твоему классу на чём его создавать >> QObject(proj)
и у тебя есть переменная bool m_bReadOnly он её срвзу при создании в false поставит smile


Автор: yngwie19 11.6.2009, 13:02
Цитата(ecspertiza @  11.6.2009,  11:45 Найти цитируемый пост)
и скажет твоему классу на чём его создавать >> QObject(proj)

немного не понял фразу. Передав в конструктор MyClass адрес объекта proj, мы им инициализируем конструктор базового класса. Вы это имеете в виду?

Автор: ecspertiza 11.6.2009, 13:24
 smile 

Ну а вызов не обязательно должен быть таким
Код

int main(int argc, char** argv)
{  
      Object *object = new Object;
      MyClass *my = new MyClass(object);
      
      return 0;
}


Ты сможешь и просто так создать

Код

int main(int argc, char** argv)
{  
      MyClass *my = new MyClass();
      return 0;
}


Автор: yngwie19 11.6.2009, 13:31
Цитата(ecspertiza @  11.6.2009,  13:24 Найти цитируемый пост)
MyClass *my = new MyClass();

т.е получается если Я в конструктор MyClass гичего не передаю, то объект Object все-равно создасться в конструкторе, о соответственно после выхода из  конструктора этот объект умрет. иак что-ли?

Автор: korbian 11.6.2009, 14:46
Цитата(yngwie19 @  11.6.2009,  14:31 Найти цитируемый пост)
т.е получается если Я в конструктор MyClass гичего не передаю, то объект Object все-равно создасться в конструкторе, о соответственно после выхода из  конструктора этот объект умрет. иак что-ли?


 yngwie19, проинициализируется та часть MyClass, которая заимствована у QObject путем наследования.

Автор: yngwie19 11.6.2009, 15:00
Цитата(korbian @  11.6.2009,  14:46 Найти цитируемый пост)
та часть MyClass, которая заимствована у QObject путем наследования.

А можно поподробнее что у меня позаимствовано от класса QObject?

Автор: korbian 11.6.2009, 15:14
yngwie19, на самом деле позаимствовано все, а доступно то, что разрешает используемый спецификатор доступа. 
Почитайте http://ru.wikipedia.org/wiki/Наследование_(программирование)  и http://alenacpp.blogspot.com/2006/03/blog-post_11.html и заодно уж про http://habrahabr.ru/blogs/cpp/58818/

Автор: JekaZZ 11.6.2009, 18:26
То ли я чего-то не понял, то ли вы куда-то не туда полезли. 

Выражение в конструкторе 
Код

: QObject(proj) 

означает не инициализацию базового класса обьектом prog, а передача указателя prog как parent (в QT это значит владелец) конструируемого объекта. 
Объект proj не создается в конструкторе MyClass, он передается в него.
Код

int main(int argc, char** argv)
{  
      Object *object = new Object;
      MyClass *my = new MyClass(object);
      
      return 0;
}

Если его не передать, то компилятор автоматически передаст NULL:
Код

MyClass(QObject *proj = 0) :...

Автор: solan 11.6.2009, 23:48
Цитата

MyClass(QObject *proj = 0) : QObject(proj), m_bReadOnly(false)


И еще уточню:
  В данном случает вызов конструктора QObject(proj)  не создает новый объект а инициализирует аттрибуты создаваемого объекта MyClass, которые наследуются у QObject (в принципе это все уже писали-) ).

  Далее вызывается конструктор аттрибута m_bReadOnly, специфичным для MyClass, с параметром, которым и инициализируется этот аттрибут. (С++ полностью объектный язык вопреки многим мнениям (конечно имхо-) ), и как класс здесь можно рассматривать абсолютно любой тип.)
 
  В целом, как писалось выше, конструкторы базовых типов, как и аттрибутов, можно не вызывать, и тогда они будут вызваны с параметрами по умолчанию неявно. Это правила ООП.

Автор: yngwie19 12.6.2009, 10:03
Почему не работает этот код:
Код

#include <QApplication>
#include <QObject>

class MyClass : public QObject
{
    Q_PROPERTY(bool readwrite READ GetValue WHRITE SetValue) 

    private:
        bool bstate;
    public:
        MyClass(QObject *obj = 0);
        void SetValue(bool);
};

int main(int argc, char *argv[])
{
    QApplication app(argc,argv);

    MyClass *my = new MyClass();
    my->setProperty("readwrite",true);
    
    
    
    return app.exec();
}

MyClass::MyClass(QObject *obj) : QObject(obj), bstate(false)
{
    
}
void MyClass::SetValue(bool bval)
{
    bstate = bval;
}


ошибки:
Код

>.\main.cpp(20) : error C2664: 'QObject::setProperty' : cannot convert parameter 2 from 'bool' to 'const QVariant &'
1>        Reason: cannot convert from 'bool' to 'const QVariant'
1>        Source or target has incomplete type

Автор: SABROG 12.6.2009, 10:05
Цитата(yngwie19 @  12.6.2009,  10:03 Найти цитируемый пост)
my->setProperty("readwrite",true);


Попробуй так:

Код

my->setProperty("readwrite",qVariantFromValue(true));

Цитата(yngwie19 @  12.6.2009,  10:03 Найти цитируемый пост)
    Q_PROPERTY(bool readwrite READ GetValue WHRITE SetValue)

А тут "WRITE" пишется без 'H'.

Автор: yngwie19 12.6.2009, 11:28
SABROG, да так работает. В книге вообще такой пример:
http://ipicture.ru/Gallery/Viewfull/19814143.html

Объясните пожалуйста, почему тут сказано что из Программы мы можем изменять и узнавать значения поля через объект proj, который является объектом класса MeClass.
И почему тут при вызове setProperty не нужно приводить к типу QVariant знчение true?

Автор: SABROG 12.6.2009, 11:36
Цитата(yngwie19 @  12.6.2009,  11:28 Найти цитируемый пост)
Объясните пожалуйста, почему тут сказано что из Программы мы можем изменять и узнавать значения поля через объект proj, который является объектом класса MeClass.

Потому, что это динамическое свойство QObject'a, который унаследован классом MeClass. По сути обычный внутренний список/массив типа QVariantMap/QVariantHash.

Цитата(yngwie19 @  12.6.2009,  11:28 Найти цитируемый пост)
И почему тут при вызове setProperty не нужно приводить к типу QVariant знчение true? 

На компиляторе gcc/MinGW использовать qVariantFromValue не требуется. Скорее всего проблема именно в компиляторе которым ты пользуешься (MSVC?).

P.S.: книги это хорошо, но в них часто забывают упомянуть некоторые тонкости, которые есть в документации, а еще книги устаревают. Поэтому лучше изучать Qt параллельно читая книги и документацию. Мне хватает последнего и примеров.

Автор: Любитель 12.6.2009, 12:02
Модератор: Пожалуйста, один топик - один вопрос.

Автор: yngwie19 12.6.2009, 12:08
Любитель, простите пожалуйста. Я специально в теме указал что несколько вопросов. Мне хочется сразу разобраться с этими свойствами.

Добавлено через 1 минуту и 33 секунды
SABROG, ой proj является объектом класса QObject  не MyClass

Добавлено через 5 минут и 19 секунд
мне все же не понятно, почему когда мы пишем:
Код

MyClass *my = new MyClass();
 
то у нас вызывается
Код

MyClass(QObject *proj = 0);

Автор: andrew_121 12.6.2009, 13:32
yngwie19, http://forum.vingrad.ru/index.php?showtopic=262908&view=findpost&p=1893904

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)