Qt访问继承类的D-Pointer

时间:2014-01-24 15:35:57

标签: c++ qt d-pointer

我试图了解整个d-pointer的工作方式。我得到了大部分内容,但我目前遇到了一个问题:

就像这里的人Dpointer inheritance我想用d-pointers继承一个类(事实上它是QProcess)。

由于访问d指针的函数是私有的,我无法通过简单的继承访问它。我的想法是再次使用Q_DECLARE_PRIVATE宏来获取函数并访问它。这可以吗?在我尝试之前,我想要一些提示,因为我不知道这是否可行。

(我需要这样做以避免整个许可问题。)

MyProcess.h

#ifndef MYPROCESS_H
#define MYPROCESS_H

class QProcessPrivate;

class MyProcess : public QProcess {
   public:
     MyProcess(QObject *parent = 0);

   protected:
     Q_DECLARE_PRIVATE(QProcessPrivate);

};

#endif /* WIDGET_H */

MyProcess.cpp

#include "myprocess.h"

MyProcess::MyProcess(QObject *parent = 0)
      : QProcess(parent) {
}

MyProcess::setPid(Q_PID pid) {
    Q_D(const QProcess);
    d->pid = pid;
}

2 个答案:

答案 0 :(得分:4)

首先,我们来介绍一下基础知识。 IANAL,但在这里:

我认为您有一个封闭源应用程序,希望根据LGPL条款使用Qt。

根据美国法律的某些解释,使您的代码依赖于Qt的私有标头使其成为Qt的衍生作品,因此您的代码必须根据LGPL(或GPL)条款提供,除非您拥有商业许可。

您在LGPL下的义务是让您分发应用程序的人能够使用您必须向他们提供的来源编译的Qt版本重新链接。这可以是由OS完成的动态链接,也可以是使用链接器实用程序完成的静态链接。是否修改了Qt并不重要。他们问,你必须向他们提供你用来构建你在应用程序中使用的Qt的确切构建脚本的Qt源。

当您依赖私有标题时,某人无法对您提供的Qt版本进行二进制兼容更改,并将其与您的代码重新链接,而不会破坏。可以在不破坏二进制兼容性的情况下更改私有Qt类 - 这就是它们为私有的原因。我自己解释LGPL如下:如果我的代码成功链接并使用任何版本的Qt,它与我提供的版本以及我的应用程序的二进制兼容,那么我的代码就不是派生工作。当然,这是在Qt错误和我做的其他更改的限制范围内,因此有人可能无法将此Qt修补到旧版本并期望它运行正常。

因此,保持代码闭源的唯一方法是在Qt中修改QProcess的* public接口。任何人都可以使用此修改版本的Qt(您提供!),对其进行进一步的二进制兼容更改,并重新链接您的代码。因此,如果您认为不修改Qt并依赖私有标题会让您的生活更轻松,您的基础非常不合适

一般来说,您不能继承QXyzPrivate,因为您需要包含Qt的私有标头。所以这不是一个好习惯,并且没有充分的理由去做。你支付的价格是你实例化课程时额外的堆分配,所以我不想担心它。

您必须启动自己的私有PIMPL类层次结构。请注意,每个打算派生的类必须提供一个构造函数来引用私有类的实例。

// myprocess.h

class MyProcessPrivate;
class MyProcess : public QProcess {
  Q_DECLARE_PRIVATE(MyProcess) // No semicolon!
public:
  explicit MyProcess(int arg, QObject * parent = 0);
  ~MyProcess();
protected:
  MyProcess(MyProcessPrivate&, int arg, QObject * parent); // Must be present to allow derivation
  const QScopedPointer<MyProcessPrivate> d_ptr; // Only in the base class, must be protected!
}

// myprocess_p.h

class MyProcessPrivate {
  Q_DECLARE_PUBLIC(MyProcess) // No semicolon!
  ...
public:
  explicit MyProcessPrivate(MyProcess*);
protected:
  MyProcess * const q_ptr; // Only in the base class, must be protected!
};

// derivedprocess.h

#include "myprocess.h"

class DerivedProcessPrivate;
class DerivedProcess {
  Q_DECLARE_PRIVATE(DerivedProcess) // No semicolon!
public:
  explicit DerivedProcess(int arg, QObject * parent = 0);
  ~DerivedProcess();
}

// derivedprocess_p.h

#include "myprocess_p.h"

class DerivedProcessPrivate : public MyProcessPrivate {
  Q_DECLARE_PUBLIC(DerivedProcess) // No semicolon!
  //...
public:
  explicit DerivedProcessPrivate(DerivedProcess*);
};

// myprocess.cpp

MyProcess::MyProcess(int arg, QObject * parent) :
  QProcess(parent),
  d_ptr(new MyProcessPrivate(this)) {}

MyProcess::MyProcess(MyProcessPrivate & d, int arg) :
  d_ptr(&d) {}

MyProcessPrivate::MyProcessPrivate(MyProcess* parent) :
  q_ptr(parent) {}

// derivedprocess.cpp

DerivedProcess::DerivedProcess(int arg, QObject * parent) :
  MyProcess(* new DerivedProcessPrivate(this), arg, parent) {}

DerivedProcessPrivate::DerivedProcessPrivate(DerivedProcess* parent) :
  MyProcessPrivate(parent) {}

答案 1 :(得分:1)

可以通过d_ptr.data()访问它。 我想扩展QML的行为而不重新编译需要访问d_ptr的Qt源代码。以下是我如何在继承类的QDeclarativeTextEdit的d_ptr中获取QTextDocument:

QT_FORWARD_DECLARE_CLASS(QDeclarativeTextEditPrivate)
class MyTextEdit : public QDeclarativeTextEdit
{
  ...
  void aMethod()
  {
    QDeclarativeTextEditPrivate *d = reinterpret_cast<QDeclarativeTextEditPrivate *>(QDeclarativeItem::d_ptr.data());
    QTextDocument *d_doc = d->document;
    ...
  }
};
不过,我们也可以在没有继承类的情况下获得d_ptr。 例如,这里是如何在没有继承的情况下在QDeclaractiveTextEditPrivate中获取QTextDocument:

#include <QtGui/QGraphicsItem>
QT_FORWARD_DECLARE_CLASS(QGraphicsItemPrivate)
class DQGraphicsItem : public QGraphicsItem
{
  DQGraphicsItem() {}
public:
  QGraphicsItemPrivate *d() const { return d_ptr.data(); }
};

inline QGraphicsItemPrivate *d_qgraphicsitem(const QGraphicsItem *q)
{ return static_cast<const DQGraphicsItem *>(q)->d(); }

#include <qt/src/declarative/graphicsitems/qdeclarativetextedit_p.h>
#include <qt/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h>

inline QDeclarativeTextEditPrivate *d_qdeclarativetextedit(const QDeclarativeTextEdit *q)
{ return static_cast<QDeclarativeTextEditPrivate *>(d_qgraphicsitem(q)); }

inline QTextDocument *d_qdeclarativetextedit_document(const QDeclarativeTextEdit *q)
{ return d_qdeclarativetextedit(q)->document; }