簡體   English   中英

QT:模板化Q_OBJECT類

[英]QT : Templated Q_OBJECT class

是否可以有一個從QObject繼承的模板類(並且在聲明中包含Q_OBJECT宏)?

我想為插槽創建類似適配器的東西,該適配器可以執行某些操作,但是插槽可以接受任意數量的參數(參數的數量取決於模板參數)。

我只是嘗試這樣做,卻出現了鏈接器錯誤。 我猜gmake或moc不會在此模板類上被調用。 有沒有辦法做到這一點? 也許通過顯式實例化模板?

不可能混合使用模板和Q_OBJECT,但是如果您有類型的子集,則可以列出插槽和信號,如下所示:

    class SignalsSlots : public QObject
    {
        Q_OBJECT

    public:
        explicit SignalsSlots(QObject *parent = 0) :
            QObject(parent) {}

    public slots:
        virtual void writeAsync(int value) {}
        virtual void writeAsync(float value) {}
        virtual void writeAsync(double value) {}
        virtual void writeAsync(bool state) {}
        virtual void writeAsync(svga::SSlideSwitch::SwitchState state) {}   

    signals:
        void readAsynkPolledChanged(int value);
        void readAsynkPolledChanged(float value);
        void readAsynkPolledChanged(double value);
        void readAsynkPolledChanged(bool state);
        void readAsynkPolledChanged(svga::SSlideSwitch::SwitchState state);
    };
...
template <class T>
class Abstraction : public SignalsSlots
{...

考慮到一些限制:可以。 首先,請熟悉(如果尚未熟悉) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html -這將有助於實現它。 關於限制:您可以有一個模板QObject類,即從QObject派生的模板類,但是:

  1. 不要告訴Moc編譯它。
  2. Q_OBJECT只是一個宏,您必須將其替換為真實內容,即虛擬接口和其他內容:)
  3. 實現QMetaObject激活(上述虛擬接口,並注意對象信息數據,該信息也來自Q_OBJECT)和其他一些功能,您將擁有模板QObject(甚至帶有模板插槽)
  4. 但是,由於我設法抓住了一個缺點-無法簡單地將此類用作另一個類別的基礎。
  5. 還有其他一些缺點-但我認為詳細調查會向您顯示它們。

希望這會有所幫助。

仍然不可能混合使用模板和Q_OBJECT,但是根據您的用例,您可以使用新的“連接”語法。 這至少允許使用模板插槽。

經典的非工作方法:

class MySignalClass : public QObject {
  Q_OBJECT
public:

signals:
  void signal_valueChanged(int newValue);
};     


template<class T>
class MySlotClass : public QObject {
  Q_OBJECT
public slots:
  void slot_setValue(const T& newValue){ /* Do sth. */}
};

所需用法,但不可編譯:

MySignalClass a;
MySlotClass<int> b;

QObject::connect(&a, SIGNAL(signal_valueChanged(int)),
                 &b, SLOT(slot_setValue(int)));

錯誤:Q_OBJECT不支持模板類(對於MySlotClass)。

使用新的“連接”語法的解決方案:

// Nothing changed here
class MySignalClass : public QObject {
  Q_OBJECT
public:

signals:
  void signal_valueChanged(int newValue);
};


// Removed Q_OBJECT and slots-keyword
template<class T>
class MySlotClass : public QObject {  // Inheritance is still required
public:
  void slot_setValue(const T& newValue){ /* Do sth. */}
};

現在,我們可以實例化所需的“ MySlotClass”對象並將其連接到適當的信號發射器。

  MySignalClass a;
  MySlotClass<int> b;

  connect(&a, &MySignalClass::signal_valueChanged,
          &b, &MySlotClass<int>::slot_setValue);

結論:可以使用模板插槽。 發射模板信號不起作用,因為由於缺少Q_OBJECT會發生編譯器錯誤。

我嘗試顯式實例化模板,並得到了:

core_qta_qt_publisheradapter.hpp:96:錯誤:Q_OBJECT不支持模板類

我想這回答了我的問題。

編輯

實際上,如果我將整個模板類定義放在標頭中,則qt預處理器不會對其進行處理,然后會出現鏈接器錯誤。 因此,如果我添加缺少的方法,那么一定有可能做到這一點。

編輯#2

這個庫正是我想要的-使用自定義信號/插槽機制,其中插槽沒有定義的簽名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM