I am trying to learn how to inherit d-pointers from a bass class using the qt example from
http://qt-project.org/wiki/Dpointer#7969fa90723037d326b77fb11381044e
I have copied it verbatim from the web site with only a slight modifaction so that the code looks like this:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
// FWD
class WidgetPrivate;
// END
class Widget {
public:
Widget();
protected:
// only sublasses may access the below
Widget(WidgetPrivate &d); // allow subclasses to initialize with their own concrete Private
WidgetPrivate *d_ptr;
};
#endif /* WIDGET_H */
widget_p.h
#ifndef WIDGET_P_H
#define WIDGET_P_H
#include <string>
#include "widget.h"
// FWD
class Widget;
// End
typedef int Rect;
typedef std::string String;
struct WidgetPrivate
{
WidgetPrivate(Widget *q) : q_ptr(q) { } // constructor that initializes the q-ptr
Widget *q_ptr; // q-ptr that points to the API class
Rect geometry;
String stylesheet;
};
#endif /* WIDGET_P_H */
widget.cpp
#include "widget.h"
Widget::Widget()
: d_ptr(new WidgetPrivate(this)) {
}
Widget::Widget(WidgetPrivate &d)
: d_ptr(&d) {
}
label.h
#ifndef LABEL_H
#define LABEL_H
#include "widget.h"
//FWD
class LabelPrivate;
//END
class Label : public Widget {
public:
Label();
protected:
Label(LabelPrivate &d); // allow Label subclasses to pass on their Private
// notice how Label does not have a d_ptr! It just uses Widget's d_ptr.
};
#endif /* LABEL_H */
label.cpp
#include "label.h"
#include "widget.h"
#include "widget_p.h"
struct LabelPrivate : public WidgetPrivate
{
String text;
};
Label::Label()
: Widget(*new LabelPrivate) // initialize the d-pointer with our own Private
{
}
Label::Label(LabelPrivate &d)
: Widget(d) {
}
When I go to compile this in g++ it gives this error
label.cpp:5:11: error: no matching function for call to ‘WidgetPrivate::WidgetPrivate()’
I have tried this in clang and I get more or less the same error so the problem has to be in the code but I have no idea where.
LabelPrivate
is inheriting fromWidgetPrivate
and the latter doesn't have a default constructor, only a constructor that takes aWidget *
. The compiler generated default constructor forLabelPrivate
will attempt to default construct its base class (WidgetPrivate
) resulting in the error. Your class definition needs to be something like this:LabelPrivate
derives publically fromWidgetPrivate
and you do not call appropriate argument taking constructor(WidgetPrivate(Widget *)
) forWidgetPrivate
in it's member initialization list.You either call the appropriate constructor or provide a constructor for
WidgetPrivate
which takes no arguments.Note that if you provide any constructor for your class the compiler does not provide for the default no argument constructor, rationale applied is that since you need to define a constructor you probably need to define each one of them yourself.