Qt “приватні слоти:” що це?


84

Я розумію, як ним користуватися, але синтаксис цього мене турбує. Що робить "приватний слот:"?

Я ніколи раніше не бачив щось між приватним ключовим словом та: у визначенні класу. Тут відбувається якась химерна магія С ++?

І приклад тут:

 #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 та слотів .
Алок Зберегти

1
При компіляції як C ++ slotsвизначається як #define slots. При компіляції за допомогою Qt MOC він генерує код для компілятора C ++.
dalle

2
хай мені це було ще важче зрозуміти, тому що я так довго не використовував C ++, я думав, що вони додали щось нове
dtc

Відповіді:


57

Слоти - це розширення C ++ для Qt. Він компілюється лише після відправки коду через препроцесор Qt, Meta-Object Compiler (moc). Див. Документацію на веб-сторінці http://doc.qt.io/qt-5/moc.html .

Редагувати: Як зазначає Френк, moc потрібен лише для посилань. Зайві ключові слова #визначаються за допомогою стандартного препроцесора.


Дякую, препроцесор Qt - це те, чого мені не вистачало в моїй ментальній моделі того, що відбувається.
Justin

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
Коли метод викликається за допомогою механізму сигнал / слот, специфікатори доступу ігноруються. Але слоти - це також "звичайні" методи. Коли ви викликаєте їх традиційним способом, враховуються специфікатори доступу.
Borges

4
@borges та будь-які майбутні читачі. У Qt5 метод connect () може використовувати покажчики функцій (що має переваги). Якщо ви підключаєтеся до покажчиків функцій, тоді специфікатори доступу застосовуються в механізмі сигналів / слотів.
Тод,

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.