Policies/Library Code Policy/Shared D-Pointer Example

From KDE TechBase
Revision as of 12:57, 17 February 2012 by Ogoffart (talk | contribs) (→‎The .cpp file: Use smart pointer)
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 QScopePointer<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 QScopePointer<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)
{
}

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)
{
}

KFooDerived::~KFooDerived()
{
}

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;
}