是否可以将基本非 QObject 类的虚函数槽化

Is it ok to slotify virtual function of base non-QObject class

本文关键字:函数 QObject 是否      更新时间:2023-10-16

如果我在基本的非 QObject 类中声明一个函数虚拟,然后将其作为派生类中的一个插槽覆盖,该类具有Q_OBJECT宏并且将 QObject 作为基类之一,它应该可以正常工作吗?

是否可以保证虚拟通话有效?如果连接到派生类的槽,会发生什么情况?

class Base
{
public:
    virtual void f();
};
class Derived: public QObject, public Base
{
    Q_OBJECT
public slots:
    virtual void f();
};

是:

由于插槽是正常的成员函数,因此它们遵循正常的C++ 直接调用时的规则。<...>您还可以将老虎机定义为虚拟的,我们发现这相当 在实践中很有用。

http://qt-project.org/doc/qt-4.8/signalsandslots.html#slots

在您的示例中,Derived::f是一个普通的虚函数。如果直接调用它,它将按预期工作,就像文档所说的那样。当由信号调用时,它由 qt_static_metacall 调用,moc_Derived.cpp生成如下:

void Derived::qt_static_metacall(QObject *_o, QMetaObject::Call _c, 
                                 int _id,     void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        Q_ASSERT(staticMetaObject.cast(_o));
        Derived *_t = static_cast<Derived *>(_o);
        switch (_id) {
        case 0: _t->f(); break;
        default: ;
        }
    }
    Q_UNUSED(_a);
}

因此,它以正常的函数调用_t->f()结束。

请注意,无法通过信号调用Base::f。仅当当前对象实际上是实例而不是实例Base Derived才能执行此函数。由于Base不是基于 QObject 的,因此您无法将其实例传递给connect函数。