Policies/Library Code Policy/Shared D-Pointer Example: Difference between revisions
(Oops I didn't mean to submit...) |
(Add note about QScopedPointer for d-pointers) |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
The following example illustrates the [[Policies/Library_Code_Policy#Shared D-Pointers|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 following example illustrates the [[Policies/Library_Code_Policy#Shared D-Pointers|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 {{qt|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 {{qt|QScopedPointer}}, otherwise your d_ptr will leak. | ||
== The header file, without Q_DECLARE_PRIVATE == | == The header file, without Q_DECLARE_PRIVATE == | ||
< | <source lang="cpp-qt"> | ||
class KFooBasePrivate; | class KFooBasePrivate; | ||
class KFooBase : public QObject | class KFooBase : public QObject | ||
Line 8: | Line 8: | ||
public: | public: | ||
KFooBase(QObject *parent); | KFooBase(QObject *parent); | ||
~KFooBase(); | |||
void setSomeInteger(int i); | void setSomeInteger(int i); | ||
int someInteger() const; | int someInteger() const; | ||
protected: | protected: | ||
KFooBasePrivate | const QScopedPointer<KFooBasePrivate> d_ptr; | ||
KFooBase(KFooBasePrivate &dd, QObject *parent); | KFooBase(KFooBasePrivate &dd, QObject *parent); | ||
private: | private: | ||
Line 32: | Line 33: | ||
friend class KFooDerivedPrivate; | friend class KFooDerivedPrivate; | ||
inline KFooDerivedPrivate *d_func() | inline KFooDerivedPrivate *d_func() | ||
{ return reinterpret_cast<KFooDerivedPrivate *>(d_ptr); } | { return reinterpret_cast<KFooDerivedPrivate *>(d_ptr.data()); } | ||
inline const KFooDerivedPrivate *d_func() const | inline const KFooDerivedPrivate *d_func() const | ||
{ return reinterpret_cast<KFooDerivedPrivate *>(d_ptr); } | { return reinterpret_cast<KFooDerivedPrivate *>(d_ptr.data()); } | ||
}; | }; | ||
</ | </source> | ||
== The header file, with Q_DECLARE_PRIVATE == | == The header file, with Q_DECLARE_PRIVATE == | ||
< | <source lang="cpp-qt"> | ||
class KFooBasePrivate; | class KFooBasePrivate; | ||
class KFooBase : public QObject | class KFooBase : public QObject | ||
Line 45: | Line 46: | ||
public: | public: | ||
KFooBase(QObject *parent); | KFooBase(QObject *parent); | ||
~KFooBase(); | |||
void setSomeInteger(int i); | void setSomeInteger(int i); | ||
int someInteger() const; | int someInteger() const; | ||
protected: | protected: | ||
KFooBasePrivate | const QScopedPointer<KFooBasePrivate> d_ptr; | ||
KFooBase(KFooBasePrivate &dd, QObject *parent); | KFooBase(KFooBasePrivate &dd, QObject *parent); | ||
private: | private: | ||
Line 67: | Line 69: | ||
Q_DECLARE_PRIVATE(KFooDerived) | Q_DECLARE_PRIVATE(KFooDerived) | ||
}; | }; | ||
</ | </source> | ||
== The .cpp file == | == The .cpp file == | ||
< | <source lang="cpp-qt"> | ||
/*** KFooBase ***/ | /*** KFooBase ***/ | ||
class KFooBasePrivate | class KFooBasePrivate | ||
Line 89: | Line 91: | ||
} | } | ||
// The destructor must be in the .cpp file, even if empty | |||
KFooBase::~KFooBase() | KFooBase::~KFooBase() | ||
{ | { | ||
} | } | ||
Line 125: | Line 127: | ||
: KFooBase(dd, parent) | : KFooBase(dd, parent) | ||
{ | { | ||
} | } | ||
Line 154: | Line 151: | ||
return d->someInteger + d->anotherInteger; | return d->someInteger + d->anotherInteger; | ||
} | } | ||
</ | </source> |
Latest revision as of 08:14, 7 January 2013
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;
}