【问题标题】:Is it ok to slotify virtual function of base non-QObject class可以槽化基非 QObject 类的虚函数吗
【发布时间】:2012-06-16 22:28:21
【问题描述】:

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

是否保证虚拟呼叫会起作用?如果连接到派生类的槽会发生什么?

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

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

【问题讨论】:

  • 显然,您的问题似乎有一些不同的解释。您能否澄清一下,例如添加一些示例代码?
  • 与问题无关,但您应该知道QObject must appear first in the list of base classes。
  • @LucTouraille 确实不相关。固定。
  • 我在回答中提供了一些细节。

标签: c++ qt


【解决方案1】:

是的:

由于槽是普通的成员函数,它们遵循普通的 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-&gt;f()结束。

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

【讨论】:

  • 这并没有真正解决问题。
  • @LucTouraille 你为什么这么认为?我认为它清楚地说明了插槽的行为类似于 normal 功能(virtualor not)。最终,槽调用导致函数调用,因此应该正确处理虚拟性。
  • @JohannesS.:据我了解,问题不在于框架明确允许的虚拟插槽(如 Riateche 所述),而在于从基础转换现有成员函数将类放入派生类的槽中(还有一个潜在问题是基类甚至不是 QObject)。
  • @LucTouraille 很抱歉,但我无法从问题中得到这种解释。如果您的解释是正确的,我会要求 OP 编辑​​问题以便清楚起见。
  • @JohannesS。 Luc Touraille 的解释是正确的,我看不出如何在我的问题中找到您的解释,无论如何我会添加代码示例以更清楚。
猜你喜欢
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多