-
Notifications
You must be signed in to change notification settings - Fork 683
D Pointer subclass lazy factory technique
Heikki Johannes Hildén edited this page Jun 22, 2016
·
1 revision
To avoid initialization order fiascoes.
// b.h
#ifndef B_H
#define B_H
#include <QWidget>
#include <QScopedPointer>
class BPrivate;
class B : public QWidget
{
Q_OBJECT
public:
explicit B(QWidget *parent = 0);
~B();
protected:
typedef BPrivate *(* BPrivateFactory)(B *);
B(BPrivateFactory factory, QWidget *parent = 0);
const QScopedPointer<BPrivate> d_ptr;
private:
Q_DISABLE_COPY(B)
Q_DECLARE_PRIVATE(B)
};
#endif // B_H
// b_p.h
#ifndef B_P_H
#define B_P_H
#include <QtGlobal>
class B;
class BPrivate
{
Q_DISABLE_COPY(BPrivate)
Q_DECLARE_PUBLIC(B)
public:
BPrivate(B *q);
virtual ~BPrivate();
B *const q_ptr;
};
#endif // B_P_H
// b.cpp
#include "b.h"
#include "b_p.h"
#include <QDebug>
BPrivate::BPrivate(B *q)
: q_ptr(q)
{
qDebug() << "BPrivate::BPrivate";
}
BPrivate::~BPrivate()
{
qDebug() << "BPrivate::~BPrivate";
}
B::B(QWidget *parent)
: QWidget(parent),
d_ptr(new BPrivate(this))
{
qDebug() << "B::B";
}
B::~B()
{
qDebug() << "B::~B";
}
B::B(BPrivateFactory factory, QWidget *parent)
: QWidget(parent),
d_ptr(factory(this))
{
qDebug() << "B::B (protected)";
}
// c.h
#ifndef C_H
#define C_H
#include "b.h"
class CPrivate;
class C : public B
{
Q_OBJECT
public:
explicit C(QWidget *parent = 0);
~C();
protected:
C(BPrivateFactory factory, QWidget *parent = 0);
private:
Q_DISABLE_COPY(C)
Q_DECLARE_PRIVATE(C)
static BPrivate *factory(B *q);
};
#endif // C_H
// c_p.h
#ifndef C_P_H
#define C_P_H
#include "b_p.h"
class C;
class CPrivate : public BPrivate
{
Q_DISABLE_COPY(CPrivate)
Q_DECLARE_PUBLIC(C)
public:
CPrivate(C *q);
~CPrivate();
};
#endif // C_P_H
// c.cpp
#include "c.h"
#include "c_p.h"
#include <QDebug>
CPrivate::CPrivate(C *q)
: BPrivate(q)
{
qDebug() << "CPrivate::CPrivate";
}
CPrivate::~CPrivate()
{
qDebug() << "CPrivate::~CPrivate";
}
C::C(QWidget *parent)
: B(&C::factory, parent)
{
qDebug() << "C::C";
}
C::~C()
{
qDebug() << "C::~C";
}
C::C(BPrivateFactory factory, QWidget *parent)
: B(factory, parent)
{
qDebug() << "C::C (protected)";
}
BPrivate *C::factory(B *q)
{
return new CPrivate(static_cast<C *>(q));
}
// d.h
#ifndef D_H
#define D_H
#include "c.h"
class DPrivate;
class D : public C
{
Q_OBJECT
public:
explicit D(QWidget *parent = 0);
~D();
private:
Q_DISABLE_COPY(D)
Q_DECLARE_PRIVATE(D)
static BPrivate *factory(B *q);
};
#endif // D_H
// d_p.h
#ifndef D_P_H
#define D_P_H
#include "c_p.h"
class D;
class DPrivate : public CPrivate
{
Q_DISABLE_COPY(DPrivate)
Q_DECLARE_PUBLIC(D)
public:
DPrivate(D *q);
~DPrivate();
};
#endif // D_P_H
// d.cpp
#include "d.h"
#include "d_p.h"
#include <QDebug>
DPrivate::DPrivate(D *q)
: CPrivate(q)
{
qDebug() << "DPrivate::DPrivate";
}
DPrivate::~DPrivate()
{
qDebug() << "DPrivate::~DPrivate";
}
D::D(QWidget *parent)
: C(&D::factory, parent)
{
qDebug() << "D::D";
}
D::~D()
{
qDebug() << "D::~D";
}
BPrivate *D::factory(B *q)
{
return new DPrivate(static_cast<D *>(q));
}
Output:
BPrivate::BPrivate
CPrivate::CPrivate
DPrivate::DPrivate
B::B (protected)
C::C (protected)
D::D
D::~D
C::~C
B::~B
DPrivate::~DPrivate
CPrivate::~CPrivate
BPrivate::~BPrivate