Russian Qt Forum

Qt => Общие вопросы => Тема начата: kuzulis от Август 23, 2009, 19:05



Название: Использование приватных классов. Проблемы. [НЕ РЕШЕНО]
Отправлено: kuzulis от Август 23, 2009, 19:05
Доброго времени суто!


При создании классов использующих QObjectPrivate, QIODevicePrivate возникли ошибки и непонятки:

1. Непонятно откуда брать хейдеры private/qinternal_p.h,  private/qiodevice_p.h: и т.п. Просмотрел исходники QT - и там хейдеры именно так и подключаются, но когда я подключаю их себе - то в консоль сыпятся ошибки:
Цитировать
...
abstractserial_p.h:7:33: error: private/qinternal_p.h: Нет такого файла или каталога
abstractserial_p.h:8:33: error: private/qiodevice_p.h: Нет такого файла или каталога
...

2. Не могу разобраться с макросами q_func() и т.п. Постоянно сырятся ошиьки что-то вроде:
Цитировать
...
abstractserialengine_p.h:77: ошибка: invalid use of incomplete type ‘struct QObjectPrivate’
/usr/include/QtCore/qobject.h:66: ошибка: forward declaration of ‘struct QObjectPrivate’
abstractserialengine_p.h: In member function ‘AbstractSerialEngine* AbstractSerialEnginePrivate::q_func()’:
abstractserialengine_p.h:78: ошибка: нет декларации ‘q_ptr’ в этой области видимости
abstractserialengine_p.h: In member function ‘const AbstractSerialEngine* AbstractSerialEnginePrivate::q_func() const’:
abstractserialengine_p.h:78: ошибка: нет декларации ‘q_ptr’ в этой области видимости
In file included from abstractserial_p.h:5,
                 from abstractserial.cpp:25:
nativeserialengine_p.h: In member function ‘NativeSerialEngine* NativeSerialEnginePrivate::q_func()’:
nativeserialengine_p.h:68: ошибка: нет декларации ‘q_ptr’ в этой области видимости
nativeserialengine_p.h: In member function ‘const NativeSerialEngine* NativeSerialEnginePrivate::q_func() const’:
nativeserialengine_p.h:68: ошибка: нет декларации ‘q_ptr’ в этой области видимости
In file included from abstractserial.cpp:25:
abstractserial_p.h: At global scope:
abstractserial_p.h:13: ошибка: invalid use of incomplete type ‘struct QIODevicePrivate’
/usr/include/QtCore/qiodevice.h:63: ошибка: forward declaration of ‘struct QIODevicePrivate’
abstractserial_p.h: In member function ‘AbstractSerial* AbstractSerialPrivate::q_func()’:
abstractserial_p.h:14: ошибка: нет декларации ‘q_ptr’ в этой области видимости
abstractserial_p.h: In member function ‘const AbstractSerial* AbstractSerialPrivate::q_func() const’:
abstractserial_p.h:14: ошибка: нет декларации ‘q_ptr’ в этой области видимости
abstractserial.cpp: In member function ‘bool AbstractSerialPrivate::initSerialLayer()’:
abstractserial.cpp:79: ошибка: нет декларации ‘resetSocketLayer’ в этой области видимости
abstractserial.cpp: In constructor ‘AbstractSerial::AbstractSerial(const QString&, QObject*)’:
abstractserial.cpp:168: ошибка: нет подходящей функции для вызова ‘QIODevice::QIODevice(AbstractSerialPrivate&, QObject*&)’
/usr/include/QtCore/qiodevice.h:166: замечание: претенденты: QIODevice::QIODevice(const QIODevice&)
/usr/include/QtCore/qiodevice.h:150: замечание:              QIODevice::QIODevice(QIODevicePrivate&, QObject*)
/usr/include/QtCore/qiodevice.h:88: замечание:              QIODevice::QIODevice(QObject*)
/usr/include/QtCore/qiodevice.h:86: замечание:              QIODevice::QIODevice()
abstractserial.cpp: In member function ‘QStringList AbstractSerial::serialDevicesAvailable() const’:
abstractserial.cpp:313: ошибка: no match for ternary ‘operator?:’ in ‘AbstractSerial::isValid() ? AbstractSerialEngine::serialDevicesAvailable() : 0’
make: *** [build/obj/abstractserial.o] Ошибка 1
[den@myhost src]$                                                                                
...

Я "слизал" структуру классов аналогично классам в исходниках QT сокетов, и не пойму в чем ошибки .  Прилагаю архив с исходниками. :) Может кто нить мне поможет разобраться в чем дело.

ЗЫ: эти исходники - попытка создать библиотеку для работы с последовательным портом по всем принципам QT4 и т.п.
ЗЫЗЫ: собирать пока что нужно пробовать в *.nix (под винду не готово еще)

Оч жду помощи!


Название: Re: Использование приватных классов. Проблемы.
Отправлено: denka от Август 23, 2009, 20:19
Насчет инклюда приват классов :

Module/private/include.h

На пример:

Код:
#include <QtCore/private/qobject_p.h>
#include <QtGui/private/qwidget_p.h>


Название: Re: Использование приватных классов. Проблемы.
Отправлено: ритт от Август 23, 2009, 21:15
эти инклюды доступны только в source-tree и недоступны после установки.


Название: Re: Использование приватных классов. Проблемы.
Отправлено: BlackTass от Август 23, 2009, 21:26
эти инклюды доступны только в source-tree и недоступны после установки.
Плюс к этому в них должно быть написано что нефиг это использовать ибо может измениться до неузнаваемости.

Я думаю стоит не заморачиваться с наследованием приватных классов от приватных кутешных, а использовать свои.


Название: Re: Использование приватных классов. Проблемы.
Отправлено: ритт от Август 24, 2009, 00:17
эти инклюды доступны только в source-tree и недоступны после установки.
Плюс к этому в них должно быть написано что нефиг это использовать ибо может измениться до неузнаваемости.

Я думаю стоит не заморачиваться с наследованием приватных классов от приватных кутешных, а использовать свои.
именно. использовние данных хедеров - дело персональное, но лучше не стОит )

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


Название: Re: Использование приватных классов. Проблемы.
Отправлено: kuzulis от Август 24, 2009, 07:34
Аха, всем спасибо за наводку, но теперь:

Цитировать
Я думаю стоит не заморачиваться с наследованием приватных классов от приватных кутешных, а использовать свои.
Цитировать
именно. использовние данных хедеров - дело персональное, но лучше не стОит )
А как свои то нарисовать (приватные классы)? Я например не представляю что туда нужно "пихать".

Цитировать
если их всё же необходимо использовать для получения доступа к некоторым приватным данным из класса-наследника, советую скопировать сам приватный хедер (или цепочку хедеров) в свой проект и убрать из них всё лишнее - впоследствии будет легче поддерживать их актуальность. но такая необходимость бывает довольно редко...
так в том и дело, что я не знаю что от туда убирать.. я щас глянул исходники QObjectPrivate - а там "мама не горюй! всего понапихано :(

1. Подскажите плз, что является лишним - а что нет в классе QObjectPrivate ? т.к. все приватные классы от него  наследуются
2. И если вдруг я решу с "нуля" создать свой приватный класс - то что в него нужно "пихать" ?

Дайте ссылки на HOWTO по использованию приватных классов и т.п. (если они имеются)



Название: Re: Использование приватных классов. Проблемы.
Отправлено: Rcus от Август 24, 2009, 07:58
KISS. Предлагаю сделать один интерфейсный класс SerialDevice, в котором будет только SerialDevicePrivate *d;
в котором будут заключены все данные. Реализация будет заключена в файлах serialdeviceprivate_posix(_p.h|.cpp) и serialdeviceprivate_win(_p.h|cpp), при сборке под разными системами будут выбираться разные файлы. И никаких вам виртуальных вызовов и использования _p заголовков Qt.

А в приватный класс надо отправлять все данные, все приватные методы и все защищенные методы не являющиеся интерфейсом класса (возможно при построении иерархии)


Название: Re: Использование приватных классов. Проблемы.
Отправлено: kuzulis от Август 24, 2009, 08:18
Цитировать
KISS. Предлагаю сделать один интерфейсный класс SerialDevice, в котором будет только SerialDevicePrivate *d;
в котором будут заключены все данные. Реализация будет заключена в файлах serialdeviceprivate_posix(_p.h|.cpp) и serialdeviceprivate_win(_p.h|cpp), при сборке под разными системами будут выбираться разные файлы. И никаких вам виртуальных вызовов и использования _p заголовков Qt.
Да я тоже сначала так подумал, но изза того, что трудно разобраться в реализации таких вещей как (по аналогии с сокетами) : использование флагов , связанных с нотификаторами и т.п. - мне проще (не разбираясь в их сути и логики) просто скопировать их из сокетов.. :) .  

Цитировать
А в приватный класс надо отправлять все данные, все приватные методы и все защищенные методы не являющиеся интерфейсом класса (возможно при построении иерархии)
Вопрос, а в таком случае этот приватный класс должен быть наследником от чего либо или же он должен быть сам по себе ? Мне вот с этим не понятно.

т.е. если например проследить (на примере сокетов) цепочку классов QObjectPrivate ->QObjectData - то в QObjectData есть следующие строки:
Код:
class QObjectData {
public:
    virtual ~QObjectData() = 0;
    QObject *q_ptr;
    QObject *parent;
    QObjectList children;
...
...
};

и в "моем" случае предполагается использование макросов     Q_D, Q_Q и т.п. .. Так вот вопрос, нужно ли при использовании этих макросов - реализовывать приватный класс с этим:
Код:
...
    QObject *q_ptr;
...

? Или же это не нужно совсем!

-----------------------------------

Прошу прощения, вот по этой ссылке: http://techbase.kde.org/Policies/Library_Code_Policy/Shared_D-Pointer_Example
вроде бы начал понимать что к чему.... Вопрос пока что приостанавливается :)


Название: Re: Использование приватных классов. Проблемы.
Отправлено: kuzulis от Август 25, 2009, 08:32
Что-то не хочет компилироваться вот этот пример:

mybaseclass.h
Код:
#ifndef MYBASECLASS_H
#define MYBASECLASS_H

#include <QObject>

class MyBasePrivateClass;
class MyBaseClass : public QObject
{
    Q_OBJECT
public:
MyBaseClass(QObject *parent = 0);
void setParam(int val);
int param() const;
protected:
    MyBasePrivateClass * const d_ptr;
//MyBaseClass(MyBasePrivateClass &dd, QObject *parent);
private:
    Q_DECLARE_PRIVATE(MyBaseClass)
    Q_DISABLE_COPY(MyBaseClass)
};

#endif

mybaseclass.cpp
Код:
#include "mybaseclass.h"


class MyBasePrivateClass
{
Q_DECLARE_PUBLIC(MyBaseClass)
public:
MyBasePrivateClass() { m_param = 0; }
virtual ~MyBasePrivateClass() {}
int m_param;
MyBaseClass *q_ptr;
};


MyBaseClass::MyBaseClass(QObject *parent)
    : QObject(parent), d_ptr(new MyBasePrivateClass)
{
   // Q_D(MyBaseClass);
}

void MyBaseClass::setParam(int val)
{
    Q_D(MyBaseClass);
d->m_param = val;
}

int MyBaseClass::param() const
{
    Q_D(const MyBaseClass);
return d->m_param;
}

Пишет:
Цитировать
D:\projects\Private_test\src>make
g++ -c -O2 -frtti -fexceptions -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_CORE_LIB -D
QT_THREAD_SUPPORT -I"D:/Qt/4.1.1/include/QtCore" -I"D:/Qt/4.1.1/include" -I"D:/Qt/4.1.1/include/Acti
veQt" -I"build\moc" -I"." -I"D:/Qt/4.1.1/mkspecs/win32-g++" -o build\obj\mybaseclass.o mybaseclass.c
pp
In file included from mybaseclass.cpp:1:
mybaseclass.h:18: error: ISO C++ forbids declaration of `MyBaseClassPrivate' with no type
mybaseclass.h:18: error: `MyBaseClassPrivate' declared as an `inline' field
mybaseclass.h:18: error: expected `;' before '*' token
mybaseclass.h:18: error: expected `;' before "inline"
mybaseclass.h:18: error: ISO C++ forbids declaration of `MyBaseClassPrivate' with no type
mybaseclass.h:18: error: `MyBaseClassPrivate' declared as an `inline' field
mybaseclass.h:18: error: expected `;' before '*' token
mybaseclass.h:18: error: expected `;' before "friend"
D:/Qt/4.1.1/include/QtCore/../../src/corelib/kernel/qobject.h: In member function `void MyBaseClass:
:setParam(int)':
D:/Qt/4.1.1/include/QtCore/../../src/corelib/kernel/qobject.h:99: error: `QObjectPrivate* QObject::d
_func()' is private
mybaseclass.cpp:23: error: within this context
mybaseclass.cpp:23: error: cannot convert `QObjectPrivate*' to `MyBaseClassPrivate* const' in initia
lization
mybaseclass.cpp:24: error: invalid use of undefined type `struct MyBaseClassPrivate'
mybaseclass.h:18: error: forward declaration of `struct MyBaseClassPrivate'
D:/Qt/4.1.1/include/QtCore/../../src/corelib/kernel/qobject.h: In member function `int MyBaseClass::
param() const':
D:/Qt/4.1.1/include/QtCore/../../src/corelib/kernel/qobject.h:99: error: `const QObjectPrivate* QObj
ect::d_func() const' is private
mybaseclass.cpp:29: error: within this context
mybaseclass.cpp:29: error: cannot convert `const QObjectPrivate*' to `MyBaseClassPrivate* const' in
initialization
mybaseclass.cpp:30: error: invalid use of undefined type `struct MyBaseClassPrivate'
mybaseclass.h:18: error: forward declaration of `struct MyBaseClassPrivate'
mingw32-make: *** [build\obj\mybaseclass.o] Error 1

D:\projects\Private_test\src>

Я уже бьюсь второй день и так и эдак меняю , переставляю члены и т.п. и все никак! :(

Не понимаю что ему нужно... поможите
ЗЫ:
Прикрепляю проект


Название: Re: Использование приватных классов. Проблемы.
Отправлено: Rcus от Август 25, 2009, 08:45
g++ -E
Код
C++ (Qt)
# 1 "/usr/include/QtCore/QObject" 2
# 5 "mybaseclass.h" 2
 
class MyBasePrivateClass;
class MyBaseClass : public QObject
{
   public: template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const { int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; } static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); static inline QString tr(const char *s, const char *c = 0) { return staticMetaObject.tr(s, c); } static inline QString trUtf8(const char *s, const char *c = 0) { return staticMetaObject.trUtf8(s, c); } static inline QString tr(const char *s, const char *c, int n) { return staticMetaObject.tr(s, c, n); } static inline QString trUtf8(const char *s, const char *c, int n) { return staticMetaObject.trUtf8(s, c, n); } virtual int qt_metacall(QMetaObject::Call, int, void **); private:
public:
MyBaseClass(QObject *parent = 0);
void setParam(int val);
int param() const;
protected:
   [b]MyBasePrivateClass[/b] * const d_ptr;
 
private:
   inline [b]MyBaseClassPrivate[/b]* d_func() { return reinterpret_cast<MyBaseClassPrivate *>(d_ptr); } inline const MyBaseClassPrivate* d_func() const { return reinterpret_cast<const MyBaseClassPrivate *>(d_ptr); } friend class MyBaseClassPrivate;
   MyBaseClass(const MyBaseClass &); MyBaseClass &operator=(const MyBaseClass &);
};
# 2 "mybaseclass.cpp" 2
 
hint :)


Название: Re: Использование приватных классов. Проблемы.
Отправлено: kuzulis от Август 25, 2009, 09:01
хм... а зачем так много то? я например хочу с использованием макросов - как описано тут : http://techbase.kde.org/Policies/Library_Code_Policy/Shared_D-Pointer_Example
The header file, with Q_DECLARE_PRIVATE

А теперь поясните в чем разница то?

ЗЫ: ничо не понял


Название: Re: Использование приватных классов. Проблемы.
Отправлено: BRE от Август 25, 2009, 09:09
А теперь поясните в чем разница то?
ЗЫ: ничо не понял
Rcus тебе показал во что разворачивается Q_DECLARE_PRIVATE(MyBaseClass). :)
Внимательно посмотри на имена классов которые он хотел bold-ом отметить.
 ;)


Название: Re: Использование приватных классов. Проблемы.
Отправлено: kuzulis от Август 25, 2009, 09:14
Цитировать
Внимательно посмотри на имена классов которые он хотел bold-ом отметить.
 Подмигивающий

И? Это опять загадка? А по простому нельзя сказать да?

Ну посмотрел я код примера из ссылки где без макросов:
Код:
class KFooBasePrivate;
class KFooBase : public QObject
{
public:
    KFooBase(QObject *parent);
    void setSomeInteger(int i);
    int someInteger() const;
protected:
    KFooBasePrivate * const d_ptr;
    KFooBase(KFooBasePrivate &dd, QObject *parent);
private:
    friend class KFooBasePrivate;
    inline KFooBasePrivate *d_func() { return d_ptr; }
    inline const KFooBasePrivate *d_func() const { return d_ptr; }
};

Аналогично все, только у меня нету KFooBase(KFooBasePrivate &dd, QObject *parent); .. а так все однотипно.. и ? в чем суть?

ЗЫ: и разница MyBasePrivateClass и MyBaseClassPrivate это с чего вдруг такая? о_О


Название: Re: Использование приватных классов. Проблемы.
Отправлено: BRE от Август 25, 2009, 09:17
И? Это опять загадка? А по простому нельзя сказать да?
Твой приватный класс называется MyBasePrivateClass.
Макрос Q_DECLARE_PRIVATE(MyBaseClass) добавит к MyBaseClass слово Private и получиться MyBaseClassPrivate.
Сравни написание.


Название: Re: Использование приватных классов. Проблемы.
Отправлено: Rcus от Август 25, 2009, 09:21
Вот же как, загадка была в вашем вопросе, я ее решил и показал решение, надо было лишь внимательно прочитать. В печаль меня вгоняют подобные явления. /** уходит совещаться с собой по поводу насущной проблемы имитации сценариев для тестирования устройств */


Название: Re: Использование приватных классов. Проблемы.
Отправлено: kuzulis от Август 25, 2009, 09:24
О_О ёпт!

никогда бы не подумал что макрос чо-то добавит сам !!! О_О О_О О_О О_О

Огромное Rcus + BRE человеческое Спасибо! :)  И на это я убил 2 дня ... мдя.. и мне тож грустно

Получается , что "как ты лодку назовешь - так она и поплывет" (с)

И главное - что нигде нет упоминания (по крайней мере я не нашел) где говорилось бы о "правильности составления имени класса"



Название: Re: Использование приватных классов. Проблемы.
Отправлено: BRE от Август 25, 2009, 09:35
И главное - что нигде нет упоминания (по крайней мере я не нашел) где говорилось бы о "правильности составления имени класса"
Как это нигде, а в /src/corelib/global/global.h  ;)
[Как мне показалось, Rcus своим ответом и хотел что бы ты туда заглянул.  :) ]


Название: Re: Использование приватных классов. Проблемы. [РЕШЕНО]
Отправлено: kuzulis от Август 25, 2009, 09:39
Кстати, а обязательно добавлять в protected секцию это:
Код:
protected:
...
MyBaseClass(MyBasePrivateClass &dd, QObject *parent);
...

?

И для чего оно нужно?


Название: Re: Использование приватных классов. Проблемы. [РЕШЕНО]
Отправлено: Rcus от Август 25, 2009, 09:46
Не обязательно. Нужно разработчику библиотеки чтобы использовать наследование интерфейсного класса совместно с раширением приватного класса.


Название: Re: Использование приватных классов. Проблемы. [РЕШЕНО]
Отправлено: kuzulis от Август 25, 2009, 09:51
Спс :)


Название: Re: Использование приватных классов. Проблемы. [НЕ РЕШЕНО]
Отправлено: kuzulis от Август 27, 2009, 14:43
Да чтож такое! Не собирается тестовый примерчик с приватными классами, пишет при сборке:

Цитировать
build\obj\mybaseclass.o(.text+0x0):mybaseclass.cpp: multiple definition of `MyBaseClass::MyBaseClass
(QObject*)'
build\obj\mybaseclass.o(.text+0x0):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0xd0):mybaseclass.cpp: multiple definition of `MyBaseClass::MyBaseClas
s(QObject*)'
build\obj\mybaseclass.o(.text+0xd0):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x1a0):mybaseclass.cpp: multiple definition of `MyBaseClass::MyBaseCla
ss(MyBaseClassPrivate&, QObject*)'
build\obj\mybaseclass.o(.text+0x1a0):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x1d0):mybaseclass.cpp: multiple definition of `MyBaseClass::MyBaseCla
ss(MyBaseClassPrivate&, QObject*)'
build\obj\mybaseclass.o(.text+0x1d0):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x200):mybaseclass.cpp: multiple definition of `MyBaseClass::~MyBaseCl
ass()'
build\obj\mybaseclass.o(.text+0x200):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x2c0):mybaseclass.cpp: multiple definition of `MyBaseClass::~MyBaseCl
ass()'
build\obj\mybaseclass.o(.text+0x2c0):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x380):mybaseclass.cpp: multiple definition of `MyBaseClass::~MyBaseCl
ass()'
build\obj\mybaseclass.o(.text+0x380):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x450):mybaseclass.cpp: multiple definition of `MyBaseClass::setParam(
int)'
build\obj\mybaseclass.o(.text+0x450):mybaseclass.cpp: first defined here
build\obj\mybaseclass.o(.text+0x470):mybaseclass.cpp: multiple definition of `MyBaseClass::param() c
onst'
build\obj\mybaseclass.o(.text+0x470):mybaseclass.cpp: first defined here
build\obj\main.o(.text+0x8d):main.cpp: undefined reference to `MyClass::MyClass(QObject*)'
collect2: ld returned 1 exit status
mingw32-make: *** [release\testprivate.exe] Error 1

что ему теперь нужно?

ЗЫ: я злой ппц . пример прилагаю


Название: Re: Использование приватных классов. Проблемы. [НЕ РЕШЕНО]
Отправлено: BRE от Август 27, 2009, 14:56
Смотри src.pro:
- SOURCES                 =       mybaseclass.cpp mybaseclass.cpp main.cpp
+ SOURCES                 =       mybaseclass.cpp myclass.cpp main.cpp

myclass.h:
protected:
-    MyClass(MyClass &dd, QObject *parent);
+    MyClass(MyClassPrivate &dd, QObject *parent);

И не нервничай так.  ;)


Название: Re: Использование приватных классов. Проблемы. [НЕ РЕШЕНО]
Отправлено: kuzulis от Август 27, 2009, 15:02
Упс, спасибо! :)