2014-01-24 72 views
1

我想了解整個d指針的工作方式。我得到了大部分零件,但我目前面臨一個問題:Qt訪問繼承類的D指針

像這裏的人Dpointer inheritance我想繼承一個類使用d指針(事實上它是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; 
} 
+0

你可以看看其他的Qt類,看看他們是如何做到這一點 –

+0

內的Qt本身,這是通過廣泛利用友元類的將涉及解決更改代碼 – user1723056

+0

@ user1723056要修補Qt的PIMPL層次結構,您只需包含私有頭文件,不需要更改代碼,但我不鼓勵這樣做 - 除非您正在編寫一個類,否則實際上毫無意義大量實例化。 –

回答

4

首先,我們要介紹的基本知識。 IANAL,但這裏是:

我認爲你有一個封閉源代碼的應用程序,希望根據LGPL的條款使用Qt。

根據美國法律的一些解釋,使您的代碼依賴於Qt的私有頭文件使其成爲Qt的派生工作,因此您的代碼必須可以根據LGPL(或GPL)提供,除非您擁有商業許可證。

你在LGPL下的義務是讓你分發你的應用程序的人可以用他們編譯的Qt版本重新鏈接你需要提供給他們的源代碼。這可能是由操作系統完成的動態鏈接,或者是使用鏈接器實用程序完成的靜態鏈接。無論您是否修改Qt都無關緊要。他們問,你必須向他們提供你用來構建你在應用中使用的Qt的精確構建腳本。

當你依賴私有頭文件時,某些人不可能對你提供的Qt版本進行二進制兼容的修改,並用你的代碼重新鏈接它,而不會中斷任何事情。私有Qt類可以在不破壞二進制兼容性的情況下進行更改 - 這就是爲什麼它們是私有的。我自己我解釋LGPL如下:我的代碼是不是派生的工作,如果它將成功地鏈接和任何版本的Qt的工作,這是與我的應用程序提供的版本二進制兼容的版本。當然,這是Qt錯誤和其他更改的限制,因此某些人可能無法將此Qt修補到較舊的版本並期望它運行正常。

所以,你可以做的唯一事情就是讓你的代碼保持閉源,在Qt中修改QProcess的*公共接口。任何人都可以使用此修改後的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) {} 
+0

對不起,如果我missunderstood你的代碼,但你不能用它來改變QProcessPrivate中的變量。你可以嗎?那就是我需要做的。 – user1723056

+0

@ user1723056你需要做什麼以及爲什麼? –

1

它可以通過d_ptr.data()訪問。 我想擴展QML的行爲,而無需重新編譯需要訪問d_ptr的Qt源代碼。以下是我得到另外,QTextDocument在QDeclarativeTextEdit的應將d_ptr在繼承類:

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繼承類。 例如,這裏就是我得到另外,QTextDocument在QDeclaractiveTextEditPrivate無繼承:

#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; }