![](/img/trans.png)
[英]QList children - struct or custom classes derived from QObject?
[英]Why is a QList not derived from a QObject?
我想在QList
周圍創建一個QObservableCollection
包裝器(使用內部QList
實現並轉發所有調用,同時為更改集合的函數發出某種CollectionsChanged信號),但我看到QList
不從QObject
繼承。
我相信你需要從QObject
繼承以發出Qt信號。 所以我需要從QObject
繼承我的QObeservableCollection。
但是QList
和QVector
以及其他Qt集合並沒有從QObject
繼承,所以我想他們必須在制作集合時遇到某種缺點或問題。
我看到QSignalSpy繼承了QObject
和QList<QList<QVariant>>
所以也許他們只是沒有看到從QObject繼承的理由?
有一個非常重要的技術原因: moc
無法處理模板,這對於通用容器類型來說幾乎是必需的。
QList是一個值類型(如std::vector
),它使用隱式共享,而QObjects必須用作指針並禁止復制
還有其他類可以反映這種用法,例如QImage
原因是簡單的容器就像值,你有assign operator,你可以復制它們克隆等等。
QObject
不能具有這樣的功能,它們不可復制。 試着想象一下當您創建具有連接的插槽和信號的對象的克隆時應該發生什么。 這會導致一團糟。 克隆對象的孩子應該怎么辦? 還應該克隆?
另一件事是模板使用。 作為QObject
類模板是moc工具的真正問題。
你需要成為QObject
才能發出信號,這當然不是真的。 你需要的就是在某處為你發出信號的QObject
。 如果您希望您的類可以直接傳遞給QObject::connect
,那么您的類應該為QObject*
提供一個轉換運算符,它返回指向這樣一個代理對象的指針。 這完全避開了整個無模板與摩洛哥的騷動。
class FrobinatorObject : public QObject {
Q_OBJECT
Q_SIGNAL void frobSignal();
...
};
template <typename T> class Frobinator {
QScopedPointer<FrobinatorObject> m_proxy;
// Could be a QSharedPointer, depending on what semantics we want
...
public:
operator FrobinatorObject*() const { return m_proxy.data(); }
};
...
Frobinator<int> frob;
QObject::connect(frob, SIGNAL(frobSignal()), ...);
// or
QObject::connect(frob, &FrobinatorObject::frobSignal, ...);
另請注意,雖然模板參數化類中不能包含信號或插槽,但您可以將它們放在基類中,然后從中派生出來。 基類可以處理類型刪除的參數。 所以:
// This won't work
template <typename T> class TemplateClass : public QObject {
Q_OBJECT
Q_SLOT void aSlot(const T *);
...
};
// But this certainly does work
class BaseClass : public QObject {
Q_OBJECT
Q_SLOT void aSlot(const void *);
...
}
template <typename T> class TemplateClass : public BaseClass {
void aMethod(const T * t) {
BaseClass::aSlot((const void*)&t);
}
...
}
TemplateClass
還可以動態地將正確類型簽名的插槽添加到BaseClass
。 雖然這需要對Qt的內部結構有所了解,但對於一個應該是可重用的框架式類的類當然可以做到。
雖然我無法深入了解開發人員的想法,但我會說沒有必要。 QList是一個簡單的容器。 它應該包含元素,允許它們的添加或刪除,迭代它們等。
它不需要父母或孩子。 對信號或插槽沒有立即需求。 這是保持簡單的問題。
如果確實需要QList提供的其他功能,那么實現起來就很容易了。 但就一般情況而言,我認為不要過度復雜化是一個合理而合乎邏輯的決定。
繼承自QObject的額外開銷對於大多數用途來說是不必要的。 容器應盡可能小和盡快。
如果您想繼承QList並為自己的類提供該功能,那么您可以這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.