2014-01-24 2 views
1

나는 전체 d-pointer가 어떻게 작동하는지 이해하려고 노력 중이다. 나는 대부분의 부분을 가지고 있지만 현재 문제에 직면하고있다 :Qt access 상속받은 클래스의 D- 포인터

남자가 여기 같다. Dpointer inheritance 나는 d- 포인터 (사실상 그것은 QProcess 임)를 사용하여 클래스를 상속하고 싶다.

d- 포인터에 액세스하는 기능이 개인이기 때문에 간단한 상속으로 액세스 할 수 없습니다. 내 생각은 다시 Q_DECLARE_PRIVATE 매크로를 사용하여 함수를 가져오고 액세스하는 것입니다. 이게 효과가 있니? 나가 시도하기 전에 나는 이것이 일할조차 모른다 cognize 때문에 몇몇 힌트를 원한다.

(나는이 전체 라이선스 문제를 방지 할 필요가있다.)

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

코드 변경 –

+0

을 어떻게보고 다른 Qt는 클래스를 볼 수 – user1723056

+0

@ user1723056 Qt의 PIMPL 계층에 패치를 적용하려면 개인 헤더를 포함하고 코드를 변경하지 않아도되지만 필요하지는 않습니다. 클래스를 작성할 때까지는 아무런 의미가 없습니다. 무겁게 인스턴스화. –

답변

4

첫째, 기초를 포함 할 수 있습니다. IANAL, 그러나 여기까지 간다 :

나는 당신이 LGPL의 조건 하에서 Qt를 사용하기를 원하는 클로즈드 소스 애플리케이션을 가지고 있다고 가정한다.

Qt의 개인 헤더에 의존적 인 코드를 작성하면 Qt의 파생물이되므로 상용 라이센스가없는 한 LGPL (또는 GPL) 약관에 따라 코드를 사용할 수 있어야합니다.

귀하가 LGPL에서 귀하에게 제공해야하는 의무는 귀하가 귀하의 앱을 배포하고 귀하가 제공해야하는 출처에서 편집 한 Qt 버전으로 다시 연결할 수있게하는 것입니다. 이것은 OS에 의해 수행되는 동적 링크이거나 링커 유틸리티로 수행 된 정적 링크 일 수 있습니다. Qt를 수정했는지 여부는 중요하지 않습니다. 그들은 여러분이 앱에서 사용하는 Qt를 빌드하는 데 사용한 정확한 빌드 스크립트로 Qt 소스를 제공해야한다고 질문합니다.

개인 헤더를 사용하는 경우 사용자가 제공하는 Qt 버전에 대해 바이너리 호환 변경을 수행하고 코드를 사용하여 링크를 해제 할 수 없습니다. 비공개 Qt 클래스는 바이너리 호환성을 손상시키지 않고 변경할 수 있습니다. 필자는 LGPL을 다음과 같이 해석합니다. 내 응용 프로그램과 함께 제공하는 버전과 이진 호환되는 모든 버전의 Qt와 성공적으로 연결하고 작업하려면 내 코드가 파생되지 않습니다. 물론 Qt 버그 및 다른 변경 사항의 한계 내이므로이 Qt를 이전 버전으로 패치하고 실행 해 볼 수는 없습니다.

코드를 닫을 수있는 유일한 방법은 Qt 내 * QProcess * 공용 인터페이스를 수정하는 것입니다. Qt의 수정 된 버전 (사용자가 제공하는!)을 사용하여 누구나 이진 호환 변경을 수행하고 코드와 다시 링크 할 수 있습니다. Qt를 수정하지 않고 개인 헤더에 따라 생활을 편하게한다고 생각한다면 입니다.

일반적으로 Qt의 개인 헤더를 포함해야하므로 QXyzPrivate에서 상속받을 수 없습니다. 따라서 그것은 좋은 습관이 아니며 실제로 그렇게할만한 이유가 없습니다. 당신이 지불하는 가격은 클래스를 인스턴스화 할 때 여분의 힙 할당이므로, 그것에 대해 걱정하지 말라고 말하고 싶습니다.

개인 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

죄송합니다. 코드를 잘못 이해했지만 QProcessPrivate 내에서 변수를 변경하는 데 사용할 수 없습니다. 너는 할수 있니? 그게 내가해야 할 일이야. – user1723056

+0

@ user1723056 정확히 무엇을해야하며 왜해야합니까? –

1

d_ptr.data()에서 액세스 할 수 있습니다. d_ptr에 액세스해야하는 Qt 소스 코드를 다시 컴파일하지 않고 QML의 동작을 확장하려고합니다. 여기에 내가 상속 클래스에서 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; 
    ... 
    } 
}; 

을 BTW, 우리는 또한 클래스를 상속하지 않고 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; } 
이를 포함 할 친구 클래스를 광범위하게 사용함으로써 해결된다 Qt는 자체 내에서 그들이