Qt «частные слоты»: что это?

84

Я понимаю, как им пользоваться, но меня беспокоит его синтаксис. Что делает "приватные слоты:"?

Я никогда раньше не видел чего-то между ключевым словом private и: в определении класса. Здесь творится какая-то причудливая магия C ++?

И пример здесь:

 #include <QObject>

 class Counter : public QObject
 {
     Q_OBJECT

 public:
     Counter() { m_value = 0; }

     int value() const { return m_value; }

 public slots:
     void setValue(int value);

 ...
Джастин
источник
3
Это не стандартный C ++, это конструкция фреймворка QT. Поиск сигналов и слотов QT .
Alok Save
1
При компиляции как C ++ slotsопределяется как #define slots. При компиляции с использованием Qt MOC он генерирует код для компилятора C ++.
dalle
2
lol, мне было еще труднее понять, потому что я так долго не использовал C ++, я подумал, что они добавили что-то новое
dtc

Ответы:

57

Слоты - это специфичное для Qt расширение C ++. Он компилируется только после отправки кода через препроцессор Qt, компилятор мета-объектов (moc). См. Http://doc.qt.io/qt-5/moc.html для документации.

Изменить: как указывает Фрэнк, moc требуется только для связывания. Дополнительные ключевые слова # определены стандартным препроцессором.

Рассел Дэвис
источник
Спасибо, препроцессор Qt - это то, чего мне не хватало в моей ментальной модели происходящего.
Джастин
16
Неправильно, код все время компилируется, поскольку «сигналы» и «слоты» являются пустыми определениями, поэтому компилятор никогда их не видит. Эти макросы являются подсказками для moc, который генерирует дополнительный код. Исходные файлы .h и .cpp не изменяются и отлично компилируются без moc. Что не удастся, так это связывание, поскольку определения, сгенерированные moc (определения сигналов, метаобъекты и т. Д.), В противном случае отсутствуют.
Фрэнк Остерфельд
1
Является ли slotsключевое слово необходимо? Я пробовал скомпилировать / связать несколько крошечных программ Qt, которые вызывают слоты без slotsключевого слова, и они отлично построились. Мои эксперименты показывают, что: signals:определенно необходимо, slotsможет быть ненужным и emitкажется ненужным, как я читал в другом месте.
It's Your App LLC
2
slotsне требуется в Qt5. Qt обновил connect()синтаксис, чтобы можно было подключать сигнал к произвольной функции, включая лямбды. Из-за этого в этом slotsнет необходимости. Однако slotsключевое слово по-прежнему влияет на способ построения объекта QMetaObject. moc(он же «компилятор метаобъектов») не распознает метод как слот, если он не находится в slots:разделе определения класса. Таким образом, хотя соединение будет работать, метод не будет отображаться в инструментах самоанализа.
Крис
19

Ключевые слова, такие как public, privateигнорируются для слотов Qt. Все слоты общедоступны и могут быть подключены

Андрей
источник
31
Когда метод вызывается через механизм сигнал / слот, спецификаторы доступа игнорируются. Но слоты тоже «нормальные» методы. Когда вы вызываете их традиционным способом, учитываются спецификаторы доступа.
боргес
4
@borges и всех будущих читателей. В Qt5 метод connect () может использовать указатели на функции (что имеет свои преимущества). Если вы подключаетесь с помощью указателей функций, то спецификаторы доступа применяются в механизме сигналов / слотов.
Tod
3
@borges Я считаю, что это неверно, или, по крайней мере, объяснение было неясным. Спецификаторы доступа не ограничивают вашу способность подключать сигналы к слотам; то есть частный слот можно подключить к любому сигналу. Однако спецификатор доступа защищает функцию-член от ее класса (обычным способом) во время ее вызова. Таким образом, спецификаторы доступа не «игнорируются» при вызове через механизм сигнал / слот: они не имеют отношения к подключению слотов к сигналам, но они защищают функцию thisтаким способом, с которым мы знакомы.
It's Your App LLC
4

Объявление слотов частными означает, что вы не сможете ссылаться на них из контекста, в котором они являются частными, как и любой другой метод. Следовательно, вы не сможете передать адрес приватных слотов connect.

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

class A{
    private:
    void e(){

    }
    public:
    auto getPointer(){
        return &A::e;   
    }
};

int main()
{
    A a;
    auto P=a.getPointer();
    (a.*P)();
}

Помимо этого, то, что упоминается в других ответах, также действительно:
- вы все равно можете подключать частные сигналы и слоты извне с помощью трюков
- signalsи slotsявляются пустыми макросами и не нарушают языковой стандарт

Эури Пинхоллоу
источник
Почему за этот вопрос нет голосов? Что-то не так? Я считаю slotsполезным утверждение, что это макрос. Я не могу подключить частные указатели-функции-слоты connectбез хитростей, можно?
Arch Linux Tux
Указатели на члены функции @ArchLinuxTux не имеют ограничений доступа .
Эури Пинхоллоу