Policies/Library Code Policy/Shared D-Pointer Example

    From KDE TechBase

    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. This example puts your d-pointer into QScopedPointer which will handle proper deleting of the d-pointer once the main object is destroyed. Be sure to delete the d-pointer properly when not using QScopedPointer, otherwise your d_ptr will leak.

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