Dpointer inheritance

2019-06-12 20:58发布

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.

2条回答
【Aperson】
2楼-- · 2019-06-12 21:18

LabelPrivate is inheriting from WidgetPrivate and the latter doesn't have a default constructor, only a constructor that takes a Widget *. The compiler generated default constructor for LabelPrivate will attempt to default construct its base class (WidgetPrivate) resulting in the error. Your class definition needs to be something like this:

struct LabelPrivate : public WidgetPrivate 
{      
  LabelPrivate( Widget *w ) : WidgetPrivate( w ) {}  
  String text;
};
查看更多
家丑人穷心不美
3楼-- · 2019-06-12 21:33

LabelPrivate derives publically from WidgetPrivate and you do not call appropriate argument taking constructor(WidgetPrivate(Widget *)) for WidgetPrivate 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.

查看更多
登录 后发表回答