(→The .cpp file) |
(Add note about QScopedPointer for d-pointers) |
||
| (12 intermediate revisions by 5 users not shown) | |||
| Line 1: | Line 1: | ||
| − | The following example illustrates the [[Policies/Library_Code_Policy#Shared D- | + | 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); | ||
int someInteger() const; | int someInteger() const; | ||
protected: | protected: | ||
| − | + | const QScopedPointer<KFooBasePrivate> d_ptr; | |
KFooBase(KFooBasePrivate &dd, QObject *parent); | KFooBase(KFooBasePrivate &dd, QObject *parent); | ||
private: | private: | ||
| Line 23: | Line 25: | ||
public: | public: | ||
KFooDerived(QObject *parent); | KFooDerived(QObject *parent); | ||
| + | void setAnotherInteger(int i); | ||
| + | int anotherInteger() const; | ||
int sumOfIntegers() const; | int sumOfIntegers() const; | ||
protected: | protected: | ||
| Line 29: | 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 42: | Line 46: | ||
public: | public: | ||
KFooBase(QObject *parent); | KFooBase(QObject *parent); | ||
| + | ~KFooBase(); | ||
| + | void setSomeInteger(int i); | ||
int someInteger() const; | int someInteger() const; | ||
protected: | protected: | ||
| − | + | const QScopedPointer<KFooBasePrivate> d_ptr; | |
KFooBase(KFooBasePrivate &dd, QObject *parent); | KFooBase(KFooBasePrivate &dd, QObject *parent); | ||
private: | private: | ||
| Line 55: | Line 61: | ||
public: | public: | ||
KFooDerived(QObject *parent); | KFooDerived(QObject *parent); | ||
| + | void setAnotherInteger(int i); | ||
| + | int anotherInteger() const; | ||
int sumOfIntegers() const; | int sumOfIntegers() const; | ||
protected: | protected: | ||
| Line 61: | 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 83: | Line 91: | ||
} | } | ||
| + | // The destructor must be in the .cpp file, even if empty | ||
KFooBase::~KFooBase() | KFooBase::~KFooBase() | ||
{ | { | ||
| − | + | } | |
| + | |||
| + | void KFooBase::setSomeInteger(int i) | ||
| + | { | ||
| + | Q_D(KFooBase); | ||
| + | |||
| + | d->someInteger = i; | ||
} | } | ||
int KFooBase::someInteger() const | int KFooBase::someInteger() const | ||
{ | { | ||
| + | // in const functions add 'const' to the class name | ||
Q_D(const KFooBase); | Q_D(const KFooBase); | ||
| + | |||
return d->someInteger; | return d->someInteger; | ||
} | } | ||
| Line 112: | Line 129: | ||
} | } | ||
| − | 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 | int KFooDerived::sumOfIntegers() const | ||
{ | { | ||
| + | // in const functions add 'const' to the class name | ||
Q_D(const KFooDerived); | Q_D(const KFooDerived); | ||
| + | |||
return d->someInteger + d->anotherInteger; | return d->someInteger + d->anotherInteger; | ||
} | } | ||
| − | </ | + | </source> |
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.
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()); } };
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) };
/*** 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; }