3

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

是否保证虚拟通话有效?如果你连接到派生类的插槽会发生什么?

class Base
{
public:
    virtual void f();
};

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

1 回答 1

8

是的:

由于槽是普通的成员函数,因此在直接调用时它们遵循普通的 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函数。

于 2012-06-13T21:50:38.897 回答