3

How do I hide the private implementation (implicit sharing) in Qt:

I have Employee.cpp the following in my Employee.h header:

#include <QSharedData>
#include <QString>


class EmployeeData;
class Employee: public QObject
{
    Q_OBJECT
    public:
    Employee();
    Employee(int id, QString name);
    Employee(const Employee &other);
    void setId(int id);
    void setName(QString name);

    int id();
    QString name();

private:
    QSharedDataPointer<EmployeeData> d;
};

class EmployeeData : public QSharedData
{
  public:
    EmployeeData() : id(-1) { name.clear(); }
    EmployeeData(const EmployeeData &other)
        : QSharedData(other), id(other.id), name(other.name) { }
    ~EmployeeData() { }

    int id;
    QString name;
};

But when I move EmployeeData to a private part, say Employee.cpp I get: error: invalid use of incomplete type ‘struct EmployeeData’

However, if I change my definition to this it works fine:

class Employee
{
public:
    Employee();
    Employee(int id, QString name);
 ..

Thus, can I use QSharedData while inheriting from QObject ?

demonplus
  • 5,613
  • 12
  • 49
  • 68
Derick Schoonbee
  • 2,971
  • 1
  • 23
  • 39

1 Answers1

2

Thus, can I use QSharedData while inheriting from QObject ?

You cannot inherit from QObject when using QSharedData. QSharedData uses copy-on-write semantics and will call detach() to create a copy of the data when it's no longer being shared. In order to do the copy, a copy-constructor is needed, which QObject does not support.

The pimpl (or handle-body/opaque-pointer idiom) will often give the data class a reference to the public implementation, which is how you're expected to work with signals and slots.

QSharedDataPointer provides most of the implementation details, but it's also quite instructive to take a look at the pimpl idiom as used in Qt (see Q_D and friends)

Kaleb Pederson
  • 45,767
  • 19
  • 102
  • 147
  • I don't see anywhere in the `QSharedDataPointer` documentation how you could store a reference to the public class. You have control over the copy constructor, but when a copy is made a reference to the parent isn't passed in, so unless the class to which the data is now attached knows that `detach()` was called, it't can't notify the data that it has a new owner. Thoughts? Suggestions? Maybe you'd need to subclass `QSharedDataPointer` to support such an operation? – Kaleb Pederson Apr 08 '10 at 20:14
  • Darn, I wanted to have my cake and eat it too! My idea was to have a data (transfer) object with 1) signals and slots, 2) pimpl AND 3) copy-on-write. I guess no bells and whistles and live with 2 and 3. Or are there some suggestions to 1+2+3 using Qt classes? – Derick Schoonbee Apr 08 '10 at 20:45
  • How would your connections transfer/copy over when your data object was copied? Why did you need signals/slots directly in the data class? – Kaleb Pederson Apr 08 '10 at 20:50
  • Q1: You got me there.. bad design ;) Once would have to disconnect,reconnect and re-parent in the copy constructor. But hey, that is not supported. Q2: The short answer is that there is some simple logic/control in state changes for fields in the DO. But, I can move it to another class or re-factor to plain methods. – Derick Schoonbee Apr 08 '10 at 21:33
  • Have to add that there is one thing I do not like in Q_D and friends is the disclaimer: This file is not part of the Qt API. It exists purely as an implementation detail. This header file may change from version to version without notice, or even be removed. – Derick Schoonbee Apr 16 '10 at 07:22