2012-06-13 4 views
3

Если я объявляю функцию виртуальной в базовом классе, отличном от QObject, а затем переопределяю ее как слот в производном классе с макросом Q_OBJECT и имеет QObject как один из базовых классов он должен работать нормально?Можно ли разрезать виртуальную функцию базового класса, отличного от QObject

Гарантировано, что виртуальные вызовы будут работать? Что произойдет, если вы подключитесь к слоту производного класса?

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

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

По-видимому, по-видимому, существуют разные интерпретации вашего вопроса. Не могли бы вы это немного пояснить, например, добавив пример кода? –

+0

Не имеет значения для вопроса, но вы должны знать, что ['QObject' должен появляться первым в списке базовых классов] (http://qt-project.org/doc/qt-4.8/moc.html#multiple- наследования требует-QObject-к-быть первым). –

+0

@ LucTouraille не соответствует действительности. исправлено. – Vasaka

ответ

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.

+2

На самом деле это не вопрос. –

+0

@LucTouraille Почему вы так думаете? Я думаю, что он четко заявляет, что слоты ведут себя как _normal_ функции ('virtual'or not). В конце концов, вызов слота приводит к вызову функции, поэтому виртуальность должна корректно обрабатываться. –

+0

@JohannesS: Насколько я понимаю, проблема заключается не в виртуальных слотах, которые явно разрешены инфраструктурой (как отмечено Riateche), а в преобразовании существующей функции-члена из базового класса в слот в производном класса (с дополнительной потенциальной проблемой, что базовый класс не является даже QObject). –

Смежные вопросы