繁体   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