Подтвердить что ты не робот

Qt-сигналы и слоты: разрешения

Существуют расхождения между уважаемыми ответами здесь на SO и фактическими документами Qt.

Я прочитал этот вопрос, и я хочу получить дополнительные разъяснения. Кто-нибудь может подтвердить:

  • Сигнал всегда protected, поэтому он может испускаться только классом или любым из его подклассов. Я не уверен, что это правда; в приведенном выше вопросе приведены ответы, подтверждающие это утверждение. Но Qt docs говорят: Signals are public access functions and can be emitted from anywhere, but we recommend to only emit them from the class that defines the signal and its subclasses. Итак, что это?
  • Слоты - это просто функции и, следовательно, могут быть общедоступными, частными или защищенными. Очевидно, что внешний класс будет иметь возможность контролировать, если ваш класс подключает один из своих собственных сигналов к одному из своих слотов, если этот слот является общедоступным. Однако снова информация SO отличается от документов, которые говорят: a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class. Это означает, что private не соблюдается механизмом сигнала/слота?
  • Слова, открытые, закрытые, защищенные, не имеют никакого отношения к работе с ключевым словом signal
  • Исходящий сигнал всегда доступен для всех других классов, то есть любой другой класс может всегда подключаться к этому сигналу (независимо от его разрешения на излучение сигнала).
  • Несмотря на то, что все сигналы доступны для просмотра всеми классами, вы все равно можете иметь два класса с сигналами с одинаковым именем, поскольку функция connect принимает имя класса в качестве префикса сигнала (т.е. SomeClass::itsSignal)
4b9b3361

Ответ 1

  • Сигналы защищены в Qt4, но являются общедоступными в Qt5, поэтому противоречивая информация.
  • Слоты - это функции, а public/protected/private соблюдаются при вызове их как таковых при подключении к сигналу, однако система метаобъектов игнорирует его.
  • Как signals определяется как public:, добавляя их, например. частные лидеры.

в

private:
public: //signals:
    void theSignal();

Таким образом, это не действует.

  • Все классы могут быть подключены к любому сигналу, правильно. Сигналы являются частью публичного API в этом отношении.
  • Наличие идентичных сигнальных сигнатур не является проблемой. Контекст определяется объектом, указанным в качестве отправителя.

Использование соединения старого стиля:

Apple *apple ... Orange* orange
connect(apple, SIGNAL(changed()), this, SLOT(appleChanged()));
connect(orange, SIGNAL(changed()), this, SLOT(orangeChanged()));

Сигнал указан как строка здесь (без имени класса в нем), но поскольку apple и orange имеют только один сигнал changed() каждый, а поиск выполняется в метаобъекте экземпляра QObject, который существует один за класс (не экземпляр), они не могут столкнуться.

Версия Qt 5 с проверкой времени компиляции:

connect(apple, &Apple::changed, this, &MyReceiver::appleChanged);

Здесь нужно указать функцию, поэтому в зависимости от области действия необходимо указать имя класса (и, возможно, пространства имен). Поскольку неоднозначное имя функции недействительно С++ и, следовательно, не компилируется, поэтому здесь можно быть безопасным.

Ответ 2

Взгляните на qobjectdefs.h (QT5.0 +). В нем определены макросы moc

#     define signals public

Как вы можете видеть, макросы, используемые в файлах заголовков для сигналов, определяются как общедоступные. Что касается явных политик statet public, private, protected, они игнорируются в разделе сигналов. В версиях версии QT версии 5.0 определены как защищенные. Они все еще доступны для соединений с использованием макроса SIGNAL().

Маскировка слотов

#     define slots

определяется как пустой макрос и поэтому может использоваться с:

public slots:
private slots:
protected slots:

Видимость метода используется для прямых вызовов метода, поэтому private/protected не может быть вызван из иностранных классов напрямую.

Использование оператора a connect по-прежнему работает независимо от видимости. Это предполагаемое поведение и реализуется в коде, создаваемом moc.

Если я правильно помню в более ранних версиях Qt, слот также был public автоматически, но я не нашел ссылку для этого сейчас.

Любой другой класс может подключаться к сигналу от внешнего класса, так как в классе указывается макрос Q_OBJECT, а иностранный класс известен (заголовок включен). Поскольку сигналы определены для каждого класса, вполне законно иметь один и тот же сигнал в разных классах. Это также довольно удобно, например, сигнал sendInfo (QString) во всех классах облегчает запоминание. Макрос Q_OBJECT заставляет moc создавать код, необходимый для подключения сигналов к слотам, независимым от видимости.

Ответ 3

Исходящий сигнал всегда доступен для всех других классов, то есть любой другой класс может всегда подключаться к этому сигналу (независимо от его разрешения на излучение сигнала).

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