Are “public slots:” sections still necessary in Qt

2019-06-16 10:55发布

问题:

A simple question regarding the new signal/slot syntax in Qt5:

  • Are there still benefits for a Q_OBJECT-derived class to have public slots:sections declared?

Note: With the new syntax you're able to connect a signal to any public function of a class or directly implement a C++11 lambda (which can also call some member functions itself).

Qt's new signal/slot syntax

回答1:

While the answers by vahancho and TheDarkKnight are valid: slots is not required for connections, but it makes the intent clearer and allows introspection. I think I should list some use cases where you do need slots.

First please note that you can use slots, Q_SLOTS, Q_SLOT or Q_INVOKABLE to make a function known to the meta object (introspection) system. Q_INVOKABLE has the advantage that it can be used on constructors.

And here are the use cases in no particular order:

  • Make your code works with Qt 4. Even if Qt 4 is not maintained I think some big company are still using it and it is fairly easy to make a library works with Qt 5 and Qt 4.
  • Make the function available in QML (and Qt Quick)
  • Make the function available in javascript (Qt Script, Qt WebEngine, etc.)
  • Make the function callable with QMetaObject::invokeMethod(). An overload that accepts functors will be available in Qt 5.10.
  • Make use of QMetaObject::connectSlotsByName(). Note that this function should not be used as it can be affected by object name collisions, but it is still the way the Qt widget designer connects the slots it creates.
  • Make your class instantiatable with QMetaObject::newInstance().
  • And every other use case that requires run-time introspection


回答2:

you're able to connect a signal to any public function of a class or directly implement a C++11 lambda

Whilst this was made available in Qt 5, which allows for compile-time verification of the slot, as opposed to when using the SIGNAL and SLOT macros, it is no longer a requirement to declare a function as a slot to connect to it.

However, for clarity I still do, as it makes the intention of a class clearer for usage, when others come to using the class.

For example:

class Foo : public QObject
{
   public: 
      Foo();

   public slots:
      void AddData();

   private:
      void CalculateStuff();
};

Just by looking at the class, we can assume that the function AddData is designed to be called via a signal; perhaps it executes on a separate thread.



回答3:

public slots: etc. declarations still needed for moc introspection if you are going to use the "old" connection style. With the new syntax this declarations do not make any sense, because, as you also noticed, "slots" are called directly by function pointers. "Slots" may even be a non class member functions as well.

However, you still need to declare your signals under signals: section of your class declaration.



回答4:

They're still needed for Qml, so that you can connect to C++ slots. However, if you want to call a C++ QObject member function, you can just declare it as Q_INVOKABLE. You don't need to make it a slot. Although using slots: might be more readable compared to using Q_INVOKABLE. Up to you.

They're also needed if you want Designer to see them. Designer has a "signal/slot" editor, and it will not list functions that are not in the slots: section. However, Designer still uses the old string-based syntax for signals and slots, so I wouldn't recommend using its signal/slot editor.