Policies/Library Code Policy/Shared D-Pointer Example

From KDE TechBase
Revision as of 13:00, 17 February 2012 by Ogoffart (talk | contribs) (s/QScopePointer/QScopedPointer/ (and few miner fixes))
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

The following example illustrates the shared d-pointer concept. The class presented here derives from QObject to illustrate parameter-passing in the constructor; it is not necessary to be like that in your code.

The header file, without Q_DECLARE_PRIVATE

class KFooBasePrivate;
class KFooBase : public QObject
{
public:
    KFooBase(QObject *parent);
    ~KFooBase();
    void setSomeInteger(int i);
    int someInteger() const;
protected:
    const QScopedPointer<KFooBasePrivate> 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; }
};

class KFooDerivedPrivate;
class KFooDerived : public KFooBase
{
public:
    KFooDerived(QObject *parent);
    void setAnotherInteger(int i);
    int anotherInteger() const;
    int sumOfIntegers() const;
protected:
    KFooDerived(KFooDerivedPrivate &dd, QObject *parent);
private:
    friend class KFooDerivedPrivate;
    inline KFooDerivedPrivate *d_func()
    { return reinterpret_cast<KFooDerivedPrivate *>(d_ptr.data()); }
    inline const KFooDerivedPrivate *d_func() const
    { return reinterpret_cast<KFooDerivedPrivate *>(d_ptr.data()); }
};

The header file, with Q_DECLARE_PRIVATE

class KFooBasePrivate;
class KFooBase : public QObject
{
public:
    KFooBase(QObject *parent);
    ~KFooBase();
    void setSomeInteger(int i);
    int someInteger() const;
protected:
    const QScopedPointer<KFooBasePrivate> d_ptr;
    KFooBase(KFooBasePrivate &dd, QObject *parent);
private:
    Q_DECLARE_PRIVATE(KFooBase)
};

class KFooDerivedPrivate;
class KFooDerived : public KFooBase
{
public:
    KFooDerived(QObject *parent);
    void setAnotherInteger(int i);
    int anotherInteger() const;
    int sumOfIntegers() const;
protected:
    KFooDerived(KFooDerivedPrivate &dd, QObject *parent);
private:
    Q_DECLARE_PRIVATE(KFooDerived)
};

The .cpp file

/*** KFooBase ***/
class KFooBasePrivate
{
public:
    virtual ~KFooBasePrivate() { }
    int someInteger;
};

KFooBase::KFooBase(QObject *parent) 
    : QObject(parent), d_ptr(new KFooBasePrivate)
{
}

KFooBase::KFooBase(KFooBasePrivate &dd, QObject *parent)
    : QObject(parent), d_ptr(&dd)
{
}

// The destructor must be in the .cpp file, even if empty
KFooBase::~KFooBase()
{
}

void KFooBase::setSomeInteger(int i)
{
    Q_D(KFooBase);

    d->someInteger = i;
}

int KFooBase::someInteger() const
{
    // in const functions add 'const' to the class name
    Q_D(const KFooBase);

    return d->someInteger;
}

/*** KFooDerived ***/

class KFooDerivedPrivate: public KFooBasePrivate
{
public:
    int anotherInteger;
};

KFooDerived::KFooDerived(QObject *parent)
    : KFooBase(*new KFooDerivedPrivate, parent)
{
}

KFooDerived::KFooDerived(KFooDerivedPrivate &dd, QObject *parent)
    : KFooBase(dd, parent)
{
}

void KFooDerived::setAnotherInteger(int i)
{
    Q_D(KFooDerived);

    d->anotherInteger = i;
}

int KFooDerived::anotherInteger() const
{
    // in const functions add 'const' to the class name
    Q_D(const KFooDerived);

    return d->anotherInteger;
}

int KFooDerived::sumOfIntegers() const
{
    // in const functions add 'const' to the class name
    Q_D(const KFooDerived);

    return d->someInteger + d->anotherInteger;
}