Russian Qt Forum

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



Название: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: kuzulis от Август 16, 2009, 16:38
Доброго дня!

Собственно сабж по теме..

Я тут принялся исходники QAbstractSocket изучать для того, чтобы на его основе написать свой класс для работы с последовательным устройством и я запнулся на преобразованиях типа d_func() , d, q и т.п... В принципе я понял суть d и q (поверхностно), а вот с d_func() ума не приложу как разбираться... т.е я уже запутался...
Меня интересует вопрос, почему тролли в классе  QAbstractSocketEngine во многих функциях (см. qabstractsocketengine.cpp) используют так:
Код:
...
QAbstractSocket::SocketState QAbstractSocketEngine::state() const
{
    return d_func()->socketState;
}

void QAbstractSocketEngine::setState(QAbstractSocket::SocketState state)
{
    d_func()->socketState = state;
}
...

Вопрос: почему они не делают через d !!!???  например типа :
Код:
...
QAbstractSocket::SocketState QAbstractSocketEngine::state() const
{
    Q_D(const QAbstractSocketEngine);
    return d->socketState;
}

void QAbstractSocketEngine::setState(QAbstractSocket::SocketState state)
{
    Q_D(const QAbstractSocketEngine);
    d->socketState = state;
}
...
И вообще: когда нужно применять d_func() а когда d ? И т.п. ?


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: Rcus от Август 16, 2009, 17:25
макрос Q_D раскрывается в объявление переменной d и инициализацию через d_func(), d_func просто обертка вокруг reinterpret_cast для d_ptr, что упрощает работу с параллельными иерархиями QObject/QObjectPrivate. Разница только в том личных представлениях об удобстве, а поскольку троллей более одного то и пишут они по-разному (самый яркий пример я нашел когда изучал нестабильность динамической сортировки в qsortfilterproxymodel.cpp - вся приватная часть написана в snake style).

А насчет вопроса что с этим делать... Именно с этими указателями ничего, http://techbase.kde.org/Policies/Library_Code_Policy#D-Pointers отвечает на вопрос как построить свою иерархию подобным образом. А вообще это все реализация [GoF,Bridge].


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: kuzulis от Август 16, 2009, 17:47
1. так я не понял все-таки... зачем делать d_func() в примерах, которые я выше привел нельзя ли это же сделать через d?
2. и еще зачем в протектед секцию добавляют еще один QAbstractSocket :
Код:
class Q_NETWORK_EXPORT QAbstractSocket : public QIODevice
{
    Q_OBJECT
public:
...
    QAbstractSocket(SocketType socketType, QObject *parent);
...
protected:
...
    QAbstractSocket(SocketType socketType, QAbstractSocketPrivate &dd, QObject *parent = 0);
...

}

это может быть связано с d_func() ?


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: Alex Custov от Август 16, 2009, 18:18
это специальный конструктор копирования, доступный только классу и наследникам класса.


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: Rcus от Август 16, 2009, 18:24
это специальный конструктор копирования, доступный только классу и наследникам класса.
/*начинает сомневаться в своей способности читать код*/


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: kuzulis от Август 16, 2009, 18:35
Цитировать
это специальный конструктор копирования, доступный только классу и наследникам класса.
а как может копироваться? если копирование отключено? :
Код:
private:
    Q_DECLARE_PRIVATE(QAbstractSocket)
    Q_DISABLE_COPY(QAbstractSocket)


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: Alex Custov от Август 16, 2009, 23:38
тьху, не копирования, конечно, а обычный. Надо меньше работать по воскресеньям ;D


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: ритт от Август 17, 2009, 06:47
1. так я не понял все-таки... зачем делать d_func() в примерах, которые я выше привел нельзя ли это же сделать через d?
Q_D(Class); return d->something;
и
return d_func()->something;
равноценны. а вот где требуетсяб олее одного обращения к d_func(), уже выгоднее использовать Q_D()

2. и еще зачем в протектед секцию добавляют еще один QAbstractSocket :
Код:
class Q_NETWORK_EXPORT QAbstractSocket : public QIODevice
{
    Q_OBJECT
public:
...
    QAbstractSocket(SocketType socketType, QObject *parent);
...
protected:
...
    QAbstractSocket(SocketType socketType, QAbstractSocketPrivate &dd, QObject *parent = 0);
...

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

а вообще, прочти хотя бы http://en.wikipedia.org/wiki/D-pointer (последнее время ссылка становится всё более популярной :) )


Название: Re: Что есть d_func(), d, q и зачем оно нужно и как с этим быть?!
Отправлено: kuzulis от Август 17, 2009, 07:22
2 Константин ,

спасибо огромное! Вот именно так я хотел услышать подтверждение моим мыслям :)

Тема пока не закрыта, буду пробовать !